mirror of
https://github.com/ansible/awx.git
synced 2024-10-31 15:21:13 +03:00
start on InventoriesLookup
This commit is contained in:
parent
d9c2bd8ef3
commit
c080346751
@ -1,5 +1,6 @@
|
|||||||
import Config from './models/Config';
|
import Config from './models/Config';
|
||||||
import InstanceGroups from './models/InstanceGroups';
|
import InstanceGroups from './models/InstanceGroups';
|
||||||
|
import Inventories from './models/Inventories';
|
||||||
import JobTemplates from './models/JobTemplates';
|
import JobTemplates from './models/JobTemplates';
|
||||||
import Jobs from './models/Jobs';
|
import Jobs from './models/Jobs';
|
||||||
import Me from './models/Me';
|
import Me from './models/Me';
|
||||||
@ -13,6 +14,7 @@ import WorkflowJobTemplates from './models/WorkflowJobTemplates';
|
|||||||
|
|
||||||
const ConfigAPI = new Config();
|
const ConfigAPI = new Config();
|
||||||
const InstanceGroupsAPI = new InstanceGroups();
|
const InstanceGroupsAPI = new InstanceGroups();
|
||||||
|
const InventoriesAPI = new Inventories();
|
||||||
const JobTemplatesAPI = new JobTemplates();
|
const JobTemplatesAPI = new JobTemplates();
|
||||||
const JobsAPI = new Jobs();
|
const JobsAPI = new Jobs();
|
||||||
const MeAPI = new Me();
|
const MeAPI = new Me();
|
||||||
@ -27,6 +29,7 @@ const WorkflowJobTemplatesAPI = new WorkflowJobTemplates();
|
|||||||
export {
|
export {
|
||||||
ConfigAPI,
|
ConfigAPI,
|
||||||
InstanceGroupsAPI,
|
InstanceGroupsAPI,
|
||||||
|
InventoriesAPI,
|
||||||
JobTemplatesAPI,
|
JobTemplatesAPI,
|
||||||
JobsAPI,
|
JobsAPI,
|
||||||
MeAPI,
|
MeAPI,
|
||||||
|
10
awx/ui_next/src/api/models/Inventories.js
Normal file
10
awx/ui_next/src/api/models/Inventories.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Base from '../Base';
|
||||||
|
|
||||||
|
class Inventories extends Base {
|
||||||
|
constructor(http) {
|
||||||
|
super(http);
|
||||||
|
this.baseUrl = '/api/v2/inventories/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Inventories;
|
@ -155,11 +155,6 @@
|
|||||||
// and bem style, as well as moved into component-based scss files
|
// and bem style, as well as moved into component-based scss files
|
||||||
//
|
//
|
||||||
|
|
||||||
.awx-lookup .pf-c-form-control {
|
|
||||||
--pf-c-form-control--Height: 90px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-c-listCardBody {
|
.at-c-listCardBody {
|
||||||
--pf-c-card__footer--PaddingX: 0;
|
--pf-c-card__footer--PaddingX: 0;
|
||||||
--pf-c-card__footer--PaddingY: 0;
|
--pf-c-card__footer--PaddingY: 0;
|
||||||
|
@ -5,11 +5,12 @@ import { SearchIcon } from '@patternfly/react-icons';
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
InputGroup,
|
InputGroup as PFInputGroup,
|
||||||
Modal,
|
Modal,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import PaginatedDataList from '../PaginatedDataList';
|
import PaginatedDataList from '../PaginatedDataList';
|
||||||
import DataListToolbar from '../DataListToolbar';
|
import DataListToolbar from '../DataListToolbar';
|
||||||
@ -18,6 +19,13 @@ import SelectedList from '../SelectedList';
|
|||||||
import { ChipGroup, Chip } from '../Chip';
|
import { ChipGroup, Chip } from '../Chip';
|
||||||
import { getQSConfig, parseNamespacedQueryString } from '../../util/qs';
|
import { getQSConfig, parseNamespacedQueryString } from '../../util/qs';
|
||||||
|
|
||||||
|
const InputGroup = styled(PFInputGroup)`
|
||||||
|
${props => props.multiple && (`
|
||||||
|
--pf-c-form-control--Height: 90px;
|
||||||
|
overflow-y: auto;
|
||||||
|
`)}
|
||||||
|
`;
|
||||||
|
|
||||||
class Lookup extends React.Component {
|
class Lookup extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -145,7 +153,7 @@ class Lookup extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<InputGroup className="awx-lookup">
|
<InputGroup>
|
||||||
<Button
|
<Button
|
||||||
aria-label="Search"
|
aria-label="Search"
|
||||||
id={id}
|
id={id}
|
||||||
@ -220,12 +228,14 @@ Lookup.propTypes = {
|
|||||||
onLookupSave: PropTypes.func.isRequired,
|
onLookupSave: PropTypes.func.isRequired,
|
||||||
value: PropTypes.arrayOf(PropTypes.object).isRequired,
|
value: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
sortedColumnKey: PropTypes.string.isRequired,
|
sortedColumnKey: PropTypes.string.isRequired,
|
||||||
|
multiple: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
Lookup.defaultProps = {
|
Lookup.defaultProps = {
|
||||||
id: 'lookup-search',
|
id: 'lookup-search',
|
||||||
lookupHeader: null,
|
lookupHeader: null,
|
||||||
name: null,
|
name: null,
|
||||||
|
multiple: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Lookup as _Lookup };
|
export { Lookup as _Lookup };
|
||||||
|
@ -35,6 +35,7 @@ class InstanceGroupsLookup extends React.Component {
|
|||||||
value={value}
|
value={value}
|
||||||
onLookupSave={onChange}
|
onLookupSave={onChange}
|
||||||
getItems={getInstanceGroups}
|
getItems={getInstanceGroups}
|
||||||
|
multiple
|
||||||
columns={[
|
columns={[
|
||||||
{ name: i18n._(t`Name`), key: 'name', isSortable: true },
|
{ name: i18n._(t`Name`), key: 'name', isSortable: true },
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { withI18n } from '@lingui/react';
|
||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { FormGroup, Tooltip } from '@patternfly/react-core';
|
||||||
|
import { QuestionCircleIcon } from '@patternfly/react-icons';
|
||||||
|
|
||||||
|
import { InventoriesAPI } from '@api';
|
||||||
|
import Lookup from '@components/Lookup';
|
||||||
|
|
||||||
|
const getInventories = async params => InventoriesAPI.read(params);
|
||||||
|
|
||||||
|
class InventoriesLookup extends React.Component {
|
||||||
|
render() {
|
||||||
|
const { value, tooltip, onChange, i18n } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormGroup
|
||||||
|
label={
|
||||||
|
<Fragment>
|
||||||
|
{i18n._(t`Inventories`)}{' '}
|
||||||
|
{tooltip && (
|
||||||
|
<Tooltip position="right" content={tooltip}>
|
||||||
|
<QuestionCircleIcon />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
fieldId="inventories-lookup"
|
||||||
|
>
|
||||||
|
<Lookup
|
||||||
|
id="inventories-lookup"
|
||||||
|
lookupHeader={i18n._(t`Inventories`)}
|
||||||
|
name="inventories"
|
||||||
|
value={value}
|
||||||
|
onLookupSave={onChange}
|
||||||
|
getItems={getInventories}
|
||||||
|
multiple
|
||||||
|
columns={[
|
||||||
|
{ name: i18n._(t`Name`), key: 'name', isSortable: true },
|
||||||
|
{
|
||||||
|
name: i18n._(t`Modified`),
|
||||||
|
key: 'modified',
|
||||||
|
isSortable: false,
|
||||||
|
isNumeric: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n._(t`Created`),
|
||||||
|
key: 'created',
|
||||||
|
isSortable: false,
|
||||||
|
isNumeric: true,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
sortedColumnKey="name"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoriesLookup.propTypes = {
|
||||||
|
value: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
tooltip: PropTypes.string,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
InventoriesLookup.defaultProps = {
|
||||||
|
tooltip: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withI18n()(InventoriesLookup);
|
@ -10,6 +10,7 @@ import AnsibleSelect from '@components/AnsibleSelect';
|
|||||||
import FormActionGroup from '@components/FormActionGroup';
|
import FormActionGroup from '@components/FormActionGroup';
|
||||||
import FormField from '@components/FormField';
|
import FormField from '@components/FormField';
|
||||||
import FormRow from '@components/FormRow';
|
import FormRow from '@components/FormRow';
|
||||||
|
import Lookup from '@components/Lookup';
|
||||||
import { required } from '@util/validators';
|
import { required } from '@util/validators';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { JobTemplate } from '@types';
|
import { JobTemplate } from '@types';
|
||||||
@ -105,7 +106,37 @@ class JobTemplateForm extends Component {
|
|||||||
</FormGroup>
|
</FormGroup>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<FormField
|
<Field
|
||||||
|
name="inventory"
|
||||||
|
validate={required(null, i18n)}
|
||||||
|
render={({ field, form }) => (
|
||||||
|
<FormGroup
|
||||||
|
fieldId="template-inventory"
|
||||||
|
helperTextInvalid={form.errors.inventory}
|
||||||
|
isRequired
|
||||||
|
label={i18n._(t`Inventory`)}
|
||||||
|
>
|
||||||
|
<Lookup
|
||||||
|
id="template-inventory"
|
||||||
|
lookupHeader={i18n._(t`Inventory`)}
|
||||||
|
name="inventory"
|
||||||
|
value={[field.value]}
|
||||||
|
onLookupSave={(value) => {console.log(value)}}
|
||||||
|
getItems={() => ({
|
||||||
|
data: {
|
||||||
|
results: [{id: 1, name: 'foo'}],
|
||||||
|
count: 1
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
columns={[
|
||||||
|
{ name: i18n._(t`Name`), key: 'name', isSortable: true},
|
||||||
|
]}
|
||||||
|
sortedColumnsKey="name"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{/* <FormField
|
||||||
id="template-inventory"
|
id="template-inventory"
|
||||||
name="inventory"
|
name="inventory"
|
||||||
type="number"
|
type="number"
|
||||||
@ -114,7 +145,7 @@ class JobTemplateForm extends Component {
|
|||||||
you want this job to manage.`)}
|
you want this job to manage.`)}
|
||||||
isRequired
|
isRequired
|
||||||
validate={required(null, i18n)}
|
validate={required(null, i18n)}
|
||||||
/>
|
/> */}
|
||||||
<FormField
|
<FormField
|
||||||
id="template-project"
|
id="template-project"
|
||||||
name="project"
|
name="project"
|
||||||
|
@ -1,7 +1,16 @@
|
|||||||
|
// TODO: switch to using Lingui i18n for pluralization
|
||||||
export function pluralize(str) {
|
export function pluralize(str) {
|
||||||
return str[str.length - 1] === 's' ? `${str}es` : `${str}s`;
|
const lastChar = str[str.length - 1];
|
||||||
|
if (lastChar === 's') {
|
||||||
|
return `${str}es`
|
||||||
|
}
|
||||||
|
if (lastChar === 'y') {
|
||||||
|
return `${str.substr(0, str.length - 1)}ies`;
|
||||||
|
}
|
||||||
|
return `${str}s`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: switch to using Lingui i18n for articles
|
||||||
export function getArticle(str) {
|
export function getArticle(str) {
|
||||||
const first = str[0];
|
const first = str[0];
|
||||||
if ('aeiou'.includes(first)) {
|
if ('aeiou'.includes(first)) {
|
||||||
|
@ -9,6 +9,10 @@ describe('string utils', () => {
|
|||||||
test('should add an "es"', () => {
|
test('should add an "es"', () => {
|
||||||
expect(pluralize('class')).toEqual('classes');
|
expect(pluralize('class')).toEqual('classes');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should handle word ending in y', () => {
|
||||||
|
expect(pluralize('inventory')).toEqual('inventories');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getArticle', () => {
|
describe('getArticle', () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user