mirror of
https://github.com/ansible/awx.git
synced 2026-01-16 20:30:46 -03:30
Add Organization Edit view
This commit is contained in:
parent
f1fefbf5f0
commit
d2cf2c275b
@ -30,9 +30,10 @@ const paginationStyling = {
|
||||
class Lookup extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
isModalOpen: false,
|
||||
lookupSelectedItems: [],
|
||||
lookupSelectedItems: props.value || [],
|
||||
results: [],
|
||||
count: 0,
|
||||
page: 1,
|
||||
@ -43,7 +44,6 @@ class Lookup extends React.Component {
|
||||
};
|
||||
this.onSetPage = this.onSetPage.bind(this);
|
||||
this.handleModalToggle = this.handleModalToggle.bind(this);
|
||||
this.wrapTags = this.wrapTags.bind(this);
|
||||
this.toggleSelected = this.toggleSelected.bind(this);
|
||||
this.saveModal = this.saveModal.bind(this);
|
||||
this.getData = this.getData.bind(this);
|
||||
|
||||
@ -119,14 +119,18 @@ class Organization extends Component {
|
||||
to="/organizations/:id/details"
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path="/organizations/:id/edit"
|
||||
render={() => (
|
||||
<OrganizationEdit
|
||||
match={match}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{organization && (
|
||||
<Route
|
||||
path="/organizations/:id/edit"
|
||||
render={() => (
|
||||
<OrganizationEdit
|
||||
api={api}
|
||||
match={match}
|
||||
organization={organization}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{organization && (
|
||||
<Route
|
||||
path="/organizations/:id/details"
|
||||
|
||||
@ -1,17 +1,293 @@
|
||||
import React from 'react';
|
||||
import { Trans } from '@lingui/macro';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { I18n, i18nMark } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import {
|
||||
Link
|
||||
} from 'react-router-dom';
|
||||
import { CardBody } from '@patternfly/react-core';
|
||||
CardBody,
|
||||
Form,
|
||||
FormGroup,
|
||||
Gallery,
|
||||
TextInput,
|
||||
} from '@patternfly/react-core';
|
||||
|
||||
const OrganizationEdit = ({ match }) => (
|
||||
<CardBody>
|
||||
<h1><Trans>edit view</Trans></h1>
|
||||
<Link to={`/organizations/${match.params.id}`}>
|
||||
<Trans>save/cancel and go back to view</Trans>
|
||||
</Link>
|
||||
</CardBody>
|
||||
);
|
||||
import { ConfigContext } from '../../../../context';
|
||||
import Lookup from '../../../../components/Lookup';
|
||||
import FormActionGroup from '../../../../components/FormActionGroup';
|
||||
import AnsibleSelect from '../../../../components/AnsibleSelect';
|
||||
|
||||
export default OrganizationEdit;
|
||||
class OrganizationEdit extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
this.getInstanceGroups = this.getInstanceGroups.bind(this);
|
||||
this.getRelatedInstanceGroups = this.getRelatedInstanceGroups.bind(this);
|
||||
this.checkValidity = this.checkValidity.bind(this);
|
||||
this.onFieldChange = this.onFieldChange.bind(this);
|
||||
this.onLookupSave = this.onLookupSave.bind(this);
|
||||
this.onSubmit = this.onSubmit.bind(this);
|
||||
this.postInstanceGroups = this.postInstanceGroups.bind(this);
|
||||
this.onCancel = this.onCancel.bind(this);
|
||||
this.onSuccess = this.onSuccess.bind(this);
|
||||
|
||||
this.state = {
|
||||
form: {
|
||||
name: {
|
||||
value: '',
|
||||
isValid: true,
|
||||
validation: {
|
||||
required: true
|
||||
},
|
||||
helperTextInvalid: i18nMark('This field must not be blank')
|
||||
},
|
||||
description: {
|
||||
value: ''
|
||||
},
|
||||
instanceGroups: {
|
||||
value: null,
|
||||
initialValue: null
|
||||
},
|
||||
custom_virtualenv: {
|
||||
value: '',
|
||||
defaultValue: '/venv/ansible/'
|
||||
}
|
||||
},
|
||||
error: '',
|
||||
formIsValid: true
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount () {
|
||||
const { organization } = this.props;
|
||||
const { form: formData } = this.state;
|
||||
|
||||
formData.name.value = organization.name;
|
||||
formData.description.value = organization.description;
|
||||
formData.custom_virtualenv.value = organization.custom_virtualenv;
|
||||
|
||||
try {
|
||||
formData.instanceGroups.value = await this.getRelatedInstanceGroups();
|
||||
formData.instanceGroups.initialValue = [...formData.instanceGroups.value];
|
||||
} catch (err) {
|
||||
this.setState({ error: err });
|
||||
}
|
||||
|
||||
this.setState({ form: formData });
|
||||
}
|
||||
|
||||
onFieldChange (val, evt) {
|
||||
const targetName = evt.target.name;
|
||||
const value = val;
|
||||
|
||||
const { form: updatedForm } = this.state;
|
||||
const updatedFormEl = { ...updatedForm[targetName] };
|
||||
|
||||
updatedFormEl.value = value;
|
||||
updatedForm[targetName] = updatedFormEl;
|
||||
|
||||
let formIsValid = true;
|
||||
if (updatedFormEl.validation) {
|
||||
updatedFormEl.isValid = this.checkValidity(updatedFormEl.value, updatedFormEl.validation);
|
||||
formIsValid = updatedFormEl.isValid && formIsValid;
|
||||
}
|
||||
|
||||
this.setState({ form: updatedForm, formIsValid });
|
||||
}
|
||||
|
||||
onLookupSave (val, targetName) {
|
||||
const { form: updatedForm } = this.state;
|
||||
updatedForm[targetName].value = val;
|
||||
|
||||
this.setState({ form: updatedForm });
|
||||
}
|
||||
|
||||
async onSubmit () {
|
||||
const { api, organization } = this.props;
|
||||
const { form: { name, description, custom_virtualenv } } = this.state;
|
||||
const formData = { name, description, custom_virtualenv };
|
||||
|
||||
const updatedData = {};
|
||||
Object.keys(formData)
|
||||
.forEach(formId => {
|
||||
updatedData[formId] = formData[formId].value;
|
||||
});
|
||||
|
||||
try {
|
||||
await api.updateOrganizationDetails(organization.id, updatedData);
|
||||
await this.postInstanceGroups();
|
||||
} catch (err) {
|
||||
this.setState({ error: err });
|
||||
} finally {
|
||||
this.onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
onCancel () {
|
||||
const { organization: { id }, history } = this.props;
|
||||
history.push(`/organizations/${id}`);
|
||||
}
|
||||
|
||||
onSuccess () {
|
||||
const { organization: { id }, history } = this.props;
|
||||
history.push(`/organizations/${id}`);
|
||||
}
|
||||
|
||||
async getInstanceGroups (params) {
|
||||
const { api } = this.props;
|
||||
const data = await api.getInstanceGroups(params);
|
||||
return data;
|
||||
}
|
||||
|
||||
async getRelatedInstanceGroups () {
|
||||
const {
|
||||
api,
|
||||
organization: { id }
|
||||
} = this.props;
|
||||
const { data } = await api.getOrganizationInstanceGroups(id);
|
||||
const { results } = data;
|
||||
return results;
|
||||
}
|
||||
|
||||
checkValidity = (value, validation) => {
|
||||
let isValid = true;
|
||||
if (validation.required) {
|
||||
isValid = value.trim() !== '' && isValid;
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
async postInstanceGroups () {
|
||||
const { api, organization } = this.props;
|
||||
const { form: { instanceGroups } } = this.state;
|
||||
const url = organization.related.instance_groups;
|
||||
|
||||
const initialInstanceGroups = instanceGroups.initialValue.map(ig => ig.id);
|
||||
const updatedInstanceGroups = instanceGroups.value.map(ig => ig.id);
|
||||
|
||||
const groupsToAssociate = [...updatedInstanceGroups]
|
||||
.filter(x => !initialInstanceGroups.includes(x));
|
||||
const groupsToDisassociate = [...initialInstanceGroups]
|
||||
.filter(x => !updatedInstanceGroups.includes(x));
|
||||
|
||||
try {
|
||||
await Promise.all(groupsToAssociate.map(async id => {
|
||||
await api.associateInstanceGroup(url, id);
|
||||
}));
|
||||
await Promise.all(groupsToDisassociate.map(async id => {
|
||||
await api.disassociateInstanceGroup(url, id);
|
||||
}));
|
||||
} catch (err) {
|
||||
this.setState({ error: err });
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
form: {
|
||||
name,
|
||||
description,
|
||||
instanceGroups,
|
||||
custom_virtualenv
|
||||
},
|
||||
formIsValid,
|
||||
error
|
||||
} = this.state;
|
||||
|
||||
const instanceGroupsLookupColumns = [
|
||||
{ name: i18nMark('Name'), key: 'name', isSortable: true },
|
||||
{ name: i18nMark('Modified'), key: 'modified', isSortable: false, isNumeric: true },
|
||||
{ name: i18nMark('Created'), key: 'created', isSortable: false, isNumeric: true }
|
||||
];
|
||||
|
||||
return (
|
||||
<CardBody>
|
||||
<Form>
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
<Gallery gutter="md">
|
||||
<FormGroup
|
||||
fieldId="edit-org-form-name"
|
||||
helperTextInvalid={name.helperTextInvalid}
|
||||
isRequired
|
||||
isValid={name.isValid}
|
||||
label={i18n._(t`Name`)}
|
||||
>
|
||||
<TextInput
|
||||
id="edit-org-form-name"
|
||||
isRequired
|
||||
isValid={name.isValid}
|
||||
name="name"
|
||||
onChange={this.onFieldChange}
|
||||
type="text"
|
||||
value={name.value || ''}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
fieldId="edit-org-form-description"
|
||||
label={i18n._(t`Description`)}
|
||||
>
|
||||
<TextInput
|
||||
id="edit-org-form-description"
|
||||
name="description"
|
||||
onChange={this.onFieldChange}
|
||||
type="text"
|
||||
value={description.value || ''}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
fieldId="edit-org-form-instance-groups"
|
||||
label={i18n._(t`Instance Groups`)}
|
||||
>
|
||||
{ instanceGroups.value
|
||||
&& (
|
||||
<Lookup
|
||||
columns={instanceGroupsLookupColumns}
|
||||
getItems={this.getInstanceGroups}
|
||||
lookupHeader="Instance Groups"
|
||||
name="instanceGroups"
|
||||
onLookupSave={this.onLookupSave}
|
||||
sortedColumnKey="name"
|
||||
value={instanceGroups.value}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</FormGroup>
|
||||
<ConfigContext.Consumer>
|
||||
{({ custom_virtualenvs }) => (
|
||||
custom_virtualenvs && custom_virtualenvs.length > 1 && (
|
||||
<FormGroup
|
||||
fieldId="edit-org-custom-virtualenv"
|
||||
label={i18n._(t`Ansible Environment`)}
|
||||
>
|
||||
<AnsibleSelect
|
||||
data={custom_virtualenvs}
|
||||
defaultSelected={custom_virtualenv.defaultEnv}
|
||||
label={i18n._(t`Ansible Environment`)}
|
||||
name="custom_virtualenv"
|
||||
onChange={this.onFieldChange}
|
||||
value={custom_virtualenv.value || ''}
|
||||
/>
|
||||
</FormGroup>
|
||||
)
|
||||
)}
|
||||
</ConfigContext.Consumer>
|
||||
</Gallery>
|
||||
)}
|
||||
</I18n>
|
||||
<FormActionGroup
|
||||
onCancel={this.onCancel}
|
||||
onSubmit={this.onSubmit}
|
||||
submitDisabled={!formIsValid}
|
||||
/>
|
||||
{ error ? <div>error</div> : '' }
|
||||
</Form>
|
||||
</CardBody>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
OrganizationEdit.contextTypes = {
|
||||
custom_virtualenvs: PropTypes.arrayOf(PropTypes.string)
|
||||
};
|
||||
|
||||
export default withRouter(OrganizationEdit);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user