mirror of
https://github.com/ansible/awx.git
synced 2026-03-22 19:35:02 -02:30
Implement basic lookup modal component.
This commit is contained in:
26
src/app.scss
26
src/app.scss
@@ -119,7 +119,33 @@
|
|||||||
--pf-c-about-modal-box--MaxWidth: 63rem;
|
--pf-c-about-modal-box--MaxWidth: 63rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pf-c-list {
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pf-c-modal-box {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
.awx-lookup {
|
||||||
|
min-height: 36px;
|
||||||
|
}
|
||||||
|
.pf-c-input-group__text {
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.awx-pill {
|
||||||
|
color: white;
|
||||||
|
background-color: rgb(0, 123, 186);
|
||||||
|
border-radius: 3px;
|
||||||
|
margin: 1px 2px;
|
||||||
|
padding: 0 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// layout styles
|
// layout styles
|
||||||
//
|
//
|
||||||
|
|||||||
89
src/components/Lookup/Lookup.jsx
Normal file
89
src/components/Lookup/Lookup.jsx
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { SearchIcon } from '@patternfly/react-icons';
|
||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Checkbox,
|
||||||
|
Button,
|
||||||
|
ActionGroup,
|
||||||
|
Toolbar,
|
||||||
|
ToolbarGroup,
|
||||||
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
|
class Lookup extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
isModalOpen: false,
|
||||||
|
}
|
||||||
|
this.handleModalToggle = this.handleModalToggle.bind(this);
|
||||||
|
this.onLookup = this.onLookup.bind(this);
|
||||||
|
this.onChecked = this.onChecked.bind(this);
|
||||||
|
this.wrapTags = this.wrapTags.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleModalToggle() {
|
||||||
|
this.setState((prevState, _) => ({
|
||||||
|
isModalOpen: !prevState.isModalOpen,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
onLookup() {
|
||||||
|
this.handleModalToggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
onChecked(_, evt) {
|
||||||
|
this.props.lookupChange(evt.target.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapTags(tags) {
|
||||||
|
return tags.filter(tag => tag.isChecked).map((tag, index) => {
|
||||||
|
return (
|
||||||
|
<span className="awx-pill" key={index}>{tag.name}</span>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { isModalOpen } = this.state;
|
||||||
|
const { data } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="pf-c-input-group awx-lookup">
|
||||||
|
<span className="pf-c-input-group__text" aria-label="search" id="search" onClick={this.onLookup}><SearchIcon /></span>
|
||||||
|
<div className="pf-c-form-control">{this.wrapTags(this.props.data)}</div>
|
||||||
|
<Modal
|
||||||
|
isLarge
|
||||||
|
title={`Select ${this.props.lookup_header}`}
|
||||||
|
isOpen={isModalOpen}
|
||||||
|
onClose={this.handleModalToggle}
|
||||||
|
>
|
||||||
|
<List>
|
||||||
|
{data.map(i =>
|
||||||
|
<ListItem key={i.id}>
|
||||||
|
<Checkbox
|
||||||
|
label={i.name}
|
||||||
|
isChecked={i.isChecked}
|
||||||
|
onChange={this.onChecked}
|
||||||
|
aria-label="result checkbox"
|
||||||
|
id={`${i.id}`}
|
||||||
|
/>
|
||||||
|
</ListItem>)}
|
||||||
|
</List>
|
||||||
|
<ActionGroup className="at-align-right">
|
||||||
|
<Toolbar>
|
||||||
|
<ToolbarGroup>
|
||||||
|
<Button className="at-C-SubmitButton" variant="primary" onClick={this.handleModalToggle} >Select</Button>
|
||||||
|
</ToolbarGroup>
|
||||||
|
<ToolbarGroup>
|
||||||
|
<Button className="at-C-CancelButton" variant="secondary" onClick={this.handleModalToggle}>Cancel</Button>
|
||||||
|
</ToolbarGroup>
|
||||||
|
</Toolbar>
|
||||||
|
</ActionGroup>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Lookup;
|
||||||
3
src/components/Lookup/index.js
Normal file
3
src/components/Lookup/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import Lookup from './Lookup';
|
||||||
|
|
||||||
|
export default Lookup;
|
||||||
@@ -4,4 +4,5 @@ export const API_LOGOUT = `${API_ROOT}logout/`;
|
|||||||
export const API_V2 = `${API_ROOT}v2/`;
|
export const API_V2 = `${API_ROOT}v2/`;
|
||||||
export const API_CONFIG = `${API_V2}config/`;
|
export const API_CONFIG = `${API_V2}config/`;
|
||||||
export const API_PROJECTS = `${API_V2}projects/`;
|
export const API_PROJECTS = `${API_V2}projects/`;
|
||||||
export const API_ORGANIZATIONS = `${API_V2}organizations/`;
|
export const API_ORGANIZATIONS = `${API_V2}organizations/`;
|
||||||
|
export const API_INSTANCE_GROUPS = `${API_V2}instance_groups/`;
|
||||||
@@ -20,8 +20,10 @@ import {
|
|||||||
|
|
||||||
import { ConfigContext } from '../../../context';
|
import { ConfigContext } from '../../../context';
|
||||||
import { API_ORGANIZATIONS } from '../../../endpoints';
|
import { API_ORGANIZATIONS } from '../../../endpoints';
|
||||||
|
import { API_INSTANCE_GROUPS } from '../../../endpoints';
|
||||||
import api from '../../../api';
|
import api from '../../../api';
|
||||||
import AnsibleSelect from '../../../components/AnsibleSelect'
|
import AnsibleSelect from '../../../components/AnsibleSelect';
|
||||||
|
import Lookup from '../../../components/Lookup';
|
||||||
const { light } = PageSectionVariants;
|
const { light } = PageSectionVariants;
|
||||||
|
|
||||||
class OrganizationAdd extends React.Component {
|
class OrganizationAdd extends React.Component {
|
||||||
@@ -30,6 +32,7 @@ class OrganizationAdd extends React.Component {
|
|||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
this.onSelectChange = this.onSelectChange.bind(this);
|
this.onSelectChange = this.onSelectChange.bind(this);
|
||||||
|
this.onLookupChange = this.onLookupChange.bind(this);
|
||||||
this.onSubmit = this.onSubmit.bind(this);
|
this.onSubmit = this.onSubmit.bind(this);
|
||||||
this.resetForm = this.resetForm.bind(this);
|
this.resetForm = this.resetForm.bind(this);
|
||||||
this.onCancel = this.onCancel.bind(this);
|
this.onCancel = this.onCancel.bind(this);
|
||||||
@@ -38,15 +41,23 @@ class OrganizationAdd extends React.Component {
|
|||||||
state = {
|
state = {
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
instanceGroups: '',
|
results: [],
|
||||||
|
instance_groups: [],
|
||||||
custom_virtualenv: '',
|
custom_virtualenv: '',
|
||||||
error:'',
|
error: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
onSelectChange(value, _) {
|
onSelectChange(value, _) {
|
||||||
this.setState({ custom_virtualenv: value });
|
this.setState({ custom_virtualenv: value });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onLookupChange(id, _) {
|
||||||
|
let selected = { ...this.state.results }
|
||||||
|
const index = id - 1;
|
||||||
|
selected[index].isChecked = !selected[index].isChecked;
|
||||||
|
this.setState({ selected })
|
||||||
|
}
|
||||||
|
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
@@ -69,10 +80,18 @@ class OrganizationAdd extends React.Component {
|
|||||||
this.props.history.push('/organizations');
|
this.props.history.push('/organizations');
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
async componentDidMount() {
|
||||||
const { name } = this.state;
|
const { data } = await api.get(API_INSTANCE_GROUPS);
|
||||||
const enabled = name.length > 0; // TODO: add better form validation
|
let results = [];
|
||||||
|
data.results.map((result) => {
|
||||||
|
results.push({ id: result.id, name: result.name, isChecked: false });
|
||||||
|
})
|
||||||
|
this.setState({ results });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { name, results } = this.state;
|
||||||
|
const enabled = name.length > 0; // TODO: add better form validation
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<PageSection variant={light} className="pf-m-condensed">
|
<PageSection variant={light} className="pf-m-condensed">
|
||||||
@@ -109,11 +128,10 @@ class OrganizationAdd extends React.Component {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
{/* LOOKUP MODAL PLACEHOLDER */}
|
{/* LOOKUP MODAL PLACEHOLDER */}
|
||||||
<FormGroup label="Instance Groups" fieldId="simple-form-instance-groups">
|
<FormGroup label="Instance Groups" fieldId="simple-form-instance-groups">
|
||||||
<TextInput
|
<Lookup
|
||||||
id="add-org-form-instance-groups"
|
lookup_header="Instance Groups"
|
||||||
name="instance-groups"
|
lookupChange={this.onLookupChange}
|
||||||
value={this.state.instanceGroups}
|
data={results}
|
||||||
onChange={this.handleChange}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<ConfigContext.Consumer>
|
<ConfigContext.Consumer>
|
||||||
|
|||||||
Reference in New Issue
Block a user