mirror of
https://github.com/ansible/awx.git
synced 2026-01-15 03:40:42 -03:30
Merge pull request #112 from mabashian/88-sort-filter-ig-modal
Adds sorting to IG lookup on org form
This commit is contained in:
commit
de3cc4637e
@ -162,6 +162,7 @@ describe('<DataListToolbar />', () => {
|
||||
onSearch={onSearch}
|
||||
onSort={onSort}
|
||||
onSelectAll={onSelectAll}
|
||||
showDelete
|
||||
/>
|
||||
</I18nProvider>
|
||||
);
|
||||
|
||||
@ -3,7 +3,10 @@ import { mount } from 'enzyme';
|
||||
import { I18nProvider } from '@lingui/react';
|
||||
import Lookup from '../../src/components/Lookup';
|
||||
|
||||
let mockData = [{ name: 'foo', id: 1 }];
|
||||
let mockData = [{ name: 'foo', id: 1, isChecked: false }];
|
||||
const mockColumns = [
|
||||
{ name: 'Name', key: 'name', isSortable: true }
|
||||
];
|
||||
describe('<Lookup />', () => {
|
||||
test('initially renders succesfully', () => {
|
||||
mount(
|
||||
@ -14,6 +17,8 @@ describe('<Lookup />', () => {
|
||||
value={mockData}
|
||||
onLookupSave={() => { }}
|
||||
getItems={() => { }}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
);
|
||||
@ -27,6 +32,8 @@ describe('<Lookup />', () => {
|
||||
value={mockData}
|
||||
onLookupSave={() => { }}
|
||||
getItems={() => ({ data: { results: [{ name: 'test instance', id: 1 }] } })}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
).find('Lookup');
|
||||
@ -47,6 +54,8 @@ describe('<Lookup />', () => {
|
||||
value={mockSelected}
|
||||
onLookupSave={() => { }}
|
||||
getItems={() => { }}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
).find('Lookup');
|
||||
@ -72,6 +81,8 @@ describe('<Lookup />', () => {
|
||||
value={mockSelected}
|
||||
onLookupSave={() => { }}
|
||||
getItems={() => ({ data: { results: [{ name: 'test instance', id: 1 }] } })}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
);
|
||||
@ -94,6 +105,8 @@ describe('<Lookup />', () => {
|
||||
value={mockData}
|
||||
onLookupSave={() => { }}
|
||||
getItems={() => { }}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
);
|
||||
@ -112,6 +125,8 @@ describe('<Lookup />', () => {
|
||||
value={mockData}
|
||||
selected={[]}
|
||||
getItems={() => { }}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
);
|
||||
@ -129,6 +144,8 @@ describe('<Lookup />', () => {
|
||||
value={mockData}
|
||||
selected={[]}
|
||||
getItems={() => { }}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
).find('Lookup');
|
||||
@ -174,4 +191,42 @@ describe('<Lookup />', () => {
|
||||
name: 'foo'
|
||||
}], 'fooBar');
|
||||
});
|
||||
test('onSort sets state and calls getData ', () => {
|
||||
const spy = jest.spyOn(Lookup.prototype, 'getData');
|
||||
const wrapper = mount(
|
||||
<I18nProvider>
|
||||
<Lookup
|
||||
lookup_header="Foo Bar"
|
||||
onLookupSave={() => { }}
|
||||
data={mockData}
|
||||
selected={[]}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
).find('Lookup');
|
||||
wrapper.instance().onSort('id', 'descending');
|
||||
expect(wrapper.state('sortedColumnKey')).toEqual('id');
|
||||
expect(wrapper.state('sortOrder')).toEqual('descending');
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
test('onSetPage sets state and calls getData ', () => {
|
||||
const spy = jest.spyOn(Lookup.prototype, 'getData');
|
||||
const wrapper = mount(
|
||||
<I18nProvider>
|
||||
<Lookup
|
||||
lookup_header="Foo Bar"
|
||||
onLookupSave={() => { }}
|
||||
data={mockData}
|
||||
selected={[]}
|
||||
columns={mockColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</I18nProvider>
|
||||
).find('Lookup');
|
||||
wrapper.instance().onSetPage(2, 10);
|
||||
expect(wrapper.state('page')).toEqual(2);
|
||||
expect(wrapper.state('page_size')).toEqual(10);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
11
__tests__/components/VerticalSeparator.test.jsx
Normal file
11
__tests__/components/VerticalSeparator.test.jsx
Normal file
@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import VerticalSeparator from '../../src/components/VerticalSeparator';
|
||||
|
||||
describe('VerticalSeparator', () => {
|
||||
test('renders the expected content', () => {
|
||||
const wrapper = mount(<VerticalSeparator />);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
@ -1 +1 @@
|
||||
/* eslint-disable */module.exports={languageData:{"plurals":function(n,ord){var s=String(n).split("."),v0=!s[1],t0=Number(s[0])==n,n10=t0&&s[0].slice(-1),n100=t0&&s[0].slice(-2);if(ord)return n10==1&&n100!=11?"one":n10==2&&n100!=12?"two":n10==3&&n100!=13?"few":"other";return n==1&&v0?"one":"other"}},messages:{"> add":"> add","> edit":"> edit","About":"About","AboutModal Logo":"AboutModal Logo","Access":"Access","Add":"Add","Administration":"Administration","Admins":"Admins","Ansible Version":"Ansible Version","Applications":"Applications","Authentication":"Authentication","Authentication Settings":"Authentication Settings","Brand Image":"Brand Image","Collapse":"Collapse","Copyright 2018 Red Hat, Inc.":"Copyright 2018 Red Hat, Inc.","Created":"Created","Credential Types":"Credential Types","Credentials":"Credentials","Dashboard":"Dashboard","Delete":"Delete","Edit":"Edit","Expand":"Expand","First":"First","Help":"Help","Instance Groups":"Instance Groups","Integrations":"Integrations","Invalid username or password. Please try again.":"Invalid username or password. Please try again.","Inventories":"Inventories","Inventory Scripts":"Inventory Scripts","Jobs":"Jobs","Jobs Settings":"Jobs Settings","Last":"Last","License":"License","Logout":"Logout","Management Jobs":"Management Jobs","Modified":"Modified","My View":"Foo","Name":"Name","Next":"Next","Notification Templates":"Notification Templates","Notifications":"Notifications","Organization Add":"Organization Add","Organization detail tabs":"Organization detail tabs","Organizations":"Organizations","Organizations List":"Organizations List","Page <0/> of {pageCount}":function(a){return["Page <0/> of ",a("pageCount")]},"Page Number":"Page Number","Password":"Password","Per Page":"Per Page","Portal Mode":"Portal Mode","Previous":"Previous","Primary Navigation":"Primary Navigation","Projects":"Projects","Resources":"Resources","Schedules":"Schedules","Search":"Search","Search text input":"Search text input","Select all":"Select all","Settings":"Settings","Sort":"Sort","System":"System","System Settings":"System Settings","Teams":"Teams","Templates":"Templates","Tower Brand Image":"Tower Brand Image","User Details":"User Details","User Interface":"User Interface","User Interface Settings":"User Interface Settings","Username":"Username","Users":"Users","Views":"Views","Welcome to Ansible Tower! Please Sign In.":"Welcome to Ansible Tower! Please Sign In.","add {currentTab}":function(a){return["add ",a("currentTab")]},"adding {currentTab}":function(a){return["adding ",a("currentTab")]},"confirm removal of {currentTab}/cancel and go back to {currentTab} view.":function(a){return["confirm removal of ",a("currentTab"),"/cancel and go back to ",a("currentTab")," view."]},"delete {currentTab}":function(a){return["delete ",a("currentTab")]},"deleting {currentTab} association with orgs":function(a){return["deleting ",a("currentTab")," association with orgs"]},"edit view":"edit view","save/cancel and go back to view":"save/cancel and go back to view","save/cancel and go back to {currentTab} view":function(a){return["save/cancel and go back to ",a("currentTab")," view"]},"select organization {itemId}":function(a){return["select organization ",a("itemId")]},"{0}":function(a){return[a("0")]},"{currentTab} detail view":function(a){return[a("currentTab")," detail view"]},"{itemMin} - {itemMax} of {count}":function(a){return[a("itemMin")," - ",a("itemMax")," of ",a("count")]}}};
|
||||
/* eslint-disable */module.exports={languageData:{"plurals":function(n,ord){var s=String(n).split("."),v0=!s[1],t0=Number(s[0])==n,n10=t0&&s[0].slice(-1),n100=t0&&s[0].slice(-2);if(ord)return n10==1&&n100!=11?"one":n10==2&&n100!=12?"two":n10==3&&n100!=13?"few":"other";return n==1&&v0?"one":"other"}},messages:{"> add":"> add","> edit":"> edit","About":"About","AboutModal Logo":"AboutModal Logo","Access":"Access","Add":"Add","Administration":"Administration","Admins":"Admins","Ansible Version":"Ansible Version","Applications":"Applications","Authentication":"Authentication","Authentication Settings":"Authentication Settings","Brand Image":"Brand Image","Collapse":"Collapse","Copyright 2018 Red Hat, Inc.":"Copyright 2018 Red Hat, Inc.","Created":"Created","Credential Types":"Credential Types","Credentials":"Credentials","Dashboard":"Dashboard","Delete":"Delete","Edit":"Edit","Expand":"Expand","First":"First","Help":"Help","Instance Groups":"Instance Groups","Integrations":"Integrations","Invalid username or password. Please try again.":"Invalid username or password. Please try again.","Inventories":"Inventories","Inventory Scripts":"Inventory Scripts","Jobs":"Jobs","Jobs Settings":"Jobs Settings","Last":"Last","License":"License","Logout":"Logout","Management Jobs":"Management Jobs","Modified":"Modified","My View":"My View","Name":"Name","Next":"Next","Notification Templates":"Notification Templates","Notifications":"Notifications","Organization Add":"Organization Add","Organization detail tabs":"Organization detail tabs","Organizations":"Organizations","Organizations List":"Organizations List","Page <0/> of {pageCount}":function(a){return["Page <0/> of ",a("pageCount")]},"Page Number":"Page Number","Password":"Password","Per Page":"Per Page","Portal Mode":"Portal Mode","Previous":"Previous","Primary Navigation":"Primary Navigation","Projects":"Projects","Resources":"Resources","Schedules":"Schedules","Search":"Search","Search text input":"Search text input","Select all":"Select all","Settings":"Settings","Sort":"Sort","System":"System","System Settings":"System Settings","Teams":"Teams","Templates":"Templates","Tower Brand Image":"Tower Brand Image","User Details":"User Details","User Interface":"User Interface","User Interface Settings":"User Interface Settings","Username":"Username","Users":"Users","Views":"Views","Welcome to Ansible Tower! Please Sign In.":"Welcome to Ansible Tower! Please Sign In.","add {currentTab}":function(a){return["add ",a("currentTab")]},"adding {currentTab}":function(a){return["adding ",a("currentTab")]},"confirm removal of {currentTab}/cancel and go back to {currentTab} view.":function(a){return["confirm removal of ",a("currentTab"),"/cancel and go back to ",a("currentTab")," view."]},"delete {currentTab}":function(a){return["delete ",a("currentTab")]},"deleting {currentTab} association with orgs":function(a){return["deleting ",a("currentTab")," association with orgs"]},"edit view":"edit view","save/cancel and go back to view":"save/cancel and go back to view","save/cancel and go back to {currentTab} view":function(a){return["save/cancel and go back to ",a("currentTab")," view"]},"select organization {itemId}":function(a){return["select organization ",a("itemId")]},"{0}":function(a){return[a("0")]},"{currentTab} detail view":function(a){return[a("currentTab")," detail view"]},"{itemMin} - {itemMax} of {count}":function(a){return[a("itemMin")," - ",a("itemMax")," of ",a("count")]}}};
|
||||
10
src/app.scss
10
src/app.scss
@ -158,10 +158,13 @@
|
||||
|
||||
.awx-c-modal.pf-c-modal-box {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
width: 550px;
|
||||
width: 600px;
|
||||
|
||||
.pf-c-button:not(:last-child) {
|
||||
.pf-c-modal-box__body {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.pf-c-modal-box__footer > .pf-c-button:not(:last-child) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
@ -233,7 +236,6 @@
|
||||
}
|
||||
|
||||
.awx-c-list {
|
||||
border-top: 1px solid #d7d7d7;
|
||||
border-bottom: 1px solid #d7d7d7;
|
||||
}
|
||||
|
||||
|
||||
@ -31,6 +31,11 @@ import {
|
||||
} from 'react-router-dom';
|
||||
|
||||
import Tooltip from '../Tooltip';
|
||||
import VerticalSeparator from '../VerticalSeparator';
|
||||
|
||||
const flexGrowStyling = {
|
||||
flexGrow: '1'
|
||||
};
|
||||
|
||||
class DataListToolbar extends React.Component {
|
||||
constructor (props) {
|
||||
@ -108,10 +113,10 @@ class DataListToolbar extends React.Component {
|
||||
addUrl,
|
||||
showExpandCollapse,
|
||||
showDelete,
|
||||
showSelectAll
|
||||
showSelectAll,
|
||||
isLookup
|
||||
} = this.props;
|
||||
const {
|
||||
// isActionDropdownOpen,
|
||||
isSearchDropdownOpen,
|
||||
isSortDropdownOpen,
|
||||
searchKey,
|
||||
@ -150,8 +155,8 @@ class DataListToolbar extends React.Component {
|
||||
{({ i18n }) => (
|
||||
<div className="awx-toolbar">
|
||||
<Level>
|
||||
<LevelItem>
|
||||
<Toolbar style={{ marginLeft: '20px' }}>
|
||||
<LevelItem style={{ display: 'flex', flexBasis: '700px' }}>
|
||||
<Toolbar style={{ marginLeft: isLookup ? '0px' : '20px', flexGrow: '1' }}>
|
||||
{ showSelectAll && (
|
||||
<ToolbarGroup>
|
||||
<ToolbarItem>
|
||||
@ -162,10 +167,11 @@ class DataListToolbar extends React.Component {
|
||||
id="select-all"
|
||||
/>
|
||||
</ToolbarItem>
|
||||
<VerticalSeparator />
|
||||
</ToolbarGroup>
|
||||
)}
|
||||
<ToolbarGroup>
|
||||
<ToolbarItem>
|
||||
<ToolbarGroup style={flexGrowStyling}>
|
||||
<ToolbarItem style={flexGrowStyling}>
|
||||
<div className="pf-c-input-group">
|
||||
<Dropdown
|
||||
className="searchKeyDropdown"
|
||||
@ -187,6 +193,7 @@ class DataListToolbar extends React.Component {
|
||||
aria-label={i18n._(t`Search text input`)}
|
||||
value={searchValue}
|
||||
onChange={this.handleSearchInputChange}
|
||||
style={{ height: '30px' }}
|
||||
/>
|
||||
<Button
|
||||
variant="tertiary"
|
||||
@ -197,26 +204,29 @@ class DataListToolbar extends React.Component {
|
||||
</Button>
|
||||
</div>
|
||||
</ToolbarItem>
|
||||
<VerticalSeparator />
|
||||
</ToolbarGroup>
|
||||
<ToolbarGroup
|
||||
className="sortDropdownGroup"
|
||||
>
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
onToggle={this.onSortDropdownToggle}
|
||||
onSelect={this.onSortDropdownSelect}
|
||||
direction={up}
|
||||
isOpen={isSortDropdownOpen}
|
||||
toggle={(
|
||||
<DropdownToggle
|
||||
onToggle={this.onSortDropdownToggle}
|
||||
>
|
||||
{sortedColumnName}
|
||||
</DropdownToggle>
|
||||
)}
|
||||
dropdownItems={sortDropdownItems}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
{ sortDropdownItems.length > 1 && (
|
||||
<ToolbarItem>
|
||||
<Dropdown
|
||||
onToggle={this.onSortDropdownToggle}
|
||||
onSelect={this.onSortDropdownSelect}
|
||||
direction={up}
|
||||
isOpen={isSortDropdownOpen}
|
||||
toggle={(
|
||||
<DropdownToggle
|
||||
onToggle={this.onSortDropdownToggle}
|
||||
>
|
||||
{sortedColumnName}
|
||||
</DropdownToggle>
|
||||
)}
|
||||
dropdownItems={sortDropdownItems}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
)}
|
||||
<ToolbarItem>
|
||||
<Button
|
||||
onClick={this.onSort}
|
||||
@ -226,6 +236,9 @@ class DataListToolbar extends React.Component {
|
||||
<SortIcon />
|
||||
</Button>
|
||||
</ToolbarItem>
|
||||
{ (showExpandCollapse || showDelete || addUrl) && (
|
||||
<VerticalSeparator />
|
||||
)}
|
||||
</ToolbarGroup>
|
||||
{showExpandCollapse && (
|
||||
<ToolbarGroup>
|
||||
@ -245,6 +258,9 @@ class DataListToolbar extends React.Component {
|
||||
<EqualsIcon />
|
||||
</Button>
|
||||
</ToolbarItem>
|
||||
{ (showDelete || addUrl) && (
|
||||
<VerticalSeparator />
|
||||
)}
|
||||
</ToolbarGroup>
|
||||
)}
|
||||
</Toolbar>
|
||||
|
||||
@ -28,16 +28,6 @@
|
||||
--pf-l-toolbar__group--MarginLeft: 0px;
|
||||
}
|
||||
|
||||
.awx-toolbar .pf-l-toolbar__group:after {
|
||||
content: "";
|
||||
background-color: #d7d7d7;
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
display: block;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.awx-toolbar button.pf-c-button {
|
||||
height: 30px;
|
||||
padding: 0px;
|
||||
@ -47,12 +37,6 @@
|
||||
min-height: 0px;
|
||||
height: 30px;
|
||||
|
||||
input {
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.pf-m-tertiary {
|
||||
width: 34px;
|
||||
padding: 0px;
|
||||
|
||||
@ -13,6 +13,7 @@ import { I18n } from '@lingui/react';
|
||||
import { Trans, t } from '@lingui/macro';
|
||||
|
||||
import CheckboxListItem from '../ListItem';
|
||||
import DataListToolbar from '../DataListToolbar';
|
||||
import SelectedList from '../SelectedList';
|
||||
import Pagination from '../Pagination';
|
||||
|
||||
@ -34,7 +35,9 @@ class Lookup extends React.Component {
|
||||
count: 0,
|
||||
page: 1,
|
||||
page_size: 5,
|
||||
error: null
|
||||
error: null,
|
||||
sortOrder: 'ascending',
|
||||
sortedColumnKey: props.sortedColumnKey
|
||||
};
|
||||
this.onSetPage = this.onSetPage.bind(this);
|
||||
this.handleModalToggle = this.handleModalToggle.bind(this);
|
||||
@ -42,6 +45,8 @@ class Lookup extends React.Component {
|
||||
this.toggleSelected = this.toggleSelected.bind(this);
|
||||
this.saveModal = this.saveModal.bind(this);
|
||||
this.getData = this.getData.bind(this);
|
||||
this.onSearch = this.onSearch.bind(this);
|
||||
this.onSort = this.onSort.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
@ -49,18 +54,35 @@ class Lookup extends React.Component {
|
||||
this.getData({ page_size, page });
|
||||
}
|
||||
|
||||
async getData (queryParams) {
|
||||
onSearch () {
|
||||
const { sortedColumnKey, sortOrder } = this.state;
|
||||
this.onSort(sortedColumnKey, sortOrder);
|
||||
}
|
||||
|
||||
onSort (sortedColumnKey, sortOrder) {
|
||||
this.setState({ page: 1, sortedColumnKey, sortOrder }, this.getData);
|
||||
}
|
||||
|
||||
async getData () {
|
||||
const { getItems } = this.props;
|
||||
const { page } = queryParams;
|
||||
const { page, page_size, sortedColumnKey, sortOrder } = this.state;
|
||||
|
||||
this.setState({ error: false });
|
||||
|
||||
const queryParams = {
|
||||
page,
|
||||
page_size
|
||||
};
|
||||
|
||||
if (sortedColumnKey) {
|
||||
queryParams.order_by = sortOrder === 'descending' ? `-${sortedColumnKey}` : sortedColumnKey;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await getItems(queryParams);
|
||||
const { results, count } = data;
|
||||
|
||||
const stateToUpdate = {
|
||||
page,
|
||||
results,
|
||||
count
|
||||
};
|
||||
@ -74,7 +96,7 @@ class Lookup extends React.Component {
|
||||
onSetPage = async (pageNumber, pageSize) => {
|
||||
const page = parseInt(pageNumber, 10);
|
||||
const page_size = parseInt(pageSize, 10);
|
||||
this.getData({ page_size, page });
|
||||
this.setState({ page, page_size }, this.getData);
|
||||
};
|
||||
|
||||
toggleSelected (row) {
|
||||
@ -124,8 +146,18 @@ class Lookup extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { isModalOpen, lookupSelectedItems, error, results, count, page, page_size } = this.state;
|
||||
const { lookupHeader, value } = this.props;
|
||||
const {
|
||||
isModalOpen,
|
||||
lookupSelectedItems,
|
||||
error,
|
||||
results,
|
||||
count,
|
||||
page,
|
||||
page_size,
|
||||
sortedColumnKey,
|
||||
sortOrder
|
||||
} = this.state;
|
||||
const { lookupHeader = 'items', value, columns } = this.props;
|
||||
|
||||
return (
|
||||
<I18n>
|
||||
@ -157,6 +189,14 @@ class Lookup extends React.Component {
|
||||
</EmptyState>
|
||||
) : (
|
||||
<Fragment>
|
||||
<DataListToolbar
|
||||
sortedColumnKey={sortedColumnKey}
|
||||
sortOrder={sortOrder}
|
||||
columns={columns}
|
||||
onSearch={this.onSearch}
|
||||
onSort={this.onSort}
|
||||
isLookup
|
||||
/>
|
||||
<ul className="pf-c-data-list awx-c-list">
|
||||
{results.map(i => (
|
||||
<CheckboxListItem
|
||||
|
||||
@ -4,6 +4,8 @@ import {
|
||||
Chip
|
||||
} from '@patternfly/react-core';
|
||||
|
||||
import VerticalSeparator from '../VerticalSeparator';
|
||||
|
||||
const selectedRowStyling = {
|
||||
paddingTop: '15px',
|
||||
paddingBottom: '5px',
|
||||
@ -41,6 +43,7 @@ class SelectedList extends Component {
|
||||
<div className="pf-l-split__item" style={selectedLabelStyling}>
|
||||
{label}
|
||||
</div>
|
||||
<VerticalSeparator />
|
||||
<div className="pf-l-split__item">
|
||||
<div className="pf-c-chip-group">
|
||||
{selected
|
||||
|
||||
@ -15,15 +15,6 @@
|
||||
white-space: nowrap;
|
||||
height: 30px;
|
||||
}
|
||||
.pf-l-split__item:not(:last-child):after {
|
||||
content: "";
|
||||
background-color: var(--awx-selectedList--BorderColor);
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
display: block;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.pf-c-chip {
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
16
src/components/VerticalSeparator/VerticalSeparator.jsx
Normal file
16
src/components/VerticalSeparator/VerticalSeparator.jsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
|
||||
const VerticalSeparator = () => (
|
||||
<span style={{
|
||||
content: '',
|
||||
backgroundColor: '#d7d7d7',
|
||||
width: '1px',
|
||||
height: '30px',
|
||||
display: 'block',
|
||||
marginLeft: '20px',
|
||||
marginRight: '20px'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
export default VerticalSeparator;
|
||||
3
src/components/VerticalSeparator/index.js
Normal file
3
src/components/VerticalSeparator/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import VerticalSeparator from './VerticalSeparator';
|
||||
|
||||
export default VerticalSeparator;
|
||||
@ -1,6 +1,8 @@
|
||||
import React 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 {
|
||||
PageSection,
|
||||
Form,
|
||||
@ -98,60 +100,71 @@ class OrganizationAdd extends React.Component {
|
||||
error
|
||||
} = this.state;
|
||||
const enabled = name.length > 0; // TODO: add better form validation
|
||||
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 (
|
||||
<PageSection>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<Form autoComplete="off">
|
||||
<Gallery gutter="md">
|
||||
<FormGroup
|
||||
label="Name"
|
||||
isRequired
|
||||
fieldId="add-org-form-name"
|
||||
>
|
||||
<TextInput
|
||||
isRequired
|
||||
id="add-org-form-name"
|
||||
name="name"
|
||||
value={name}
|
||||
onChange={this.onFieldChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label="Description" fieldId="add-org-form-description">
|
||||
<TextInput
|
||||
id="add-org-form-description"
|
||||
name="description"
|
||||
value={description}
|
||||
onChange={this.onFieldChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label="Instance Groups" fieldId="add-org-form-instance-groups">
|
||||
<Lookup
|
||||
lookupHeader="Instance Groups"
|
||||
name="instanceGroups"
|
||||
value={instanceGroups}
|
||||
onLookupSave={this.onLookupSave}
|
||||
getItems={this.getInstanceGroups}
|
||||
/>
|
||||
</FormGroup>
|
||||
<ConfigContext.Consumer>
|
||||
{({ custom_virtualenvs }) => (
|
||||
custom_virtualenvs && custom_virtualenvs.length > 1 && (
|
||||
<FormGroup label="Ansible Environment" fieldId="add-org-custom-virtualenv">
|
||||
<AnsibleSelect
|
||||
label="Ansible Environment"
|
||||
name="custom_virtualenv"
|
||||
value={custom_virtualenv}
|
||||
onChange={this.onFieldChange}
|
||||
data={custom_virtualenvs}
|
||||
defaultSelected={defaultEnv}
|
||||
/>
|
||||
</FormGroup>
|
||||
)
|
||||
)}
|
||||
</ConfigContext.Consumer>
|
||||
</Gallery>
|
||||
<I18n>
|
||||
{({ i18n }) => (
|
||||
<Gallery gutter="md">
|
||||
<FormGroup
|
||||
label={i18n._(t`Name`)}
|
||||
isRequired
|
||||
fieldId="add-org-form-name"
|
||||
>
|
||||
<TextInput
|
||||
isRequired
|
||||
id="add-org-form-name"
|
||||
name="name"
|
||||
value={name}
|
||||
onChange={this.onFieldChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={i18n._(t`Description`)} fieldId="add-org-form-description">
|
||||
<TextInput
|
||||
id="add-org-form-description"
|
||||
name="description"
|
||||
value={description}
|
||||
onChange={this.onFieldChange}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup label={i18n._(t`Instance Groups`)} fieldId="add-org-form-instance-groups">
|
||||
<Lookup
|
||||
lookupHeader={i18n._(t`Instance Groups`)}
|
||||
name="instanceGroups"
|
||||
value={instanceGroups}
|
||||
onLookupSave={this.onLookupSave}
|
||||
getItems={this.getInstanceGroups}
|
||||
columns={instanceGroupsLookupColumns}
|
||||
sortedColumnKey="name"
|
||||
/>
|
||||
</FormGroup>
|
||||
<ConfigContext.Consumer>
|
||||
{({ custom_virtualenvs }) => (
|
||||
custom_virtualenvs && custom_virtualenvs.length > 1 && (
|
||||
<FormGroup label={i18n._(t`Ansible Environment`)} fieldId="add-org-custom-virtualenv">
|
||||
<AnsibleSelect
|
||||
label={i18n._(t`Ansible Environment`)}
|
||||
name="custom_virtualenv"
|
||||
value={custom_virtualenv}
|
||||
onChange={this.onFieldChange}
|
||||
data={custom_virtualenvs}
|
||||
defaultSelected={defaultEnv}
|
||||
/>
|
||||
</FormGroup>
|
||||
)
|
||||
)}
|
||||
</ConfigContext.Consumer>
|
||||
</Gallery>
|
||||
)}
|
||||
</I18n>
|
||||
<FormActionGroup
|
||||
onSubmit={this.onSubmit}
|
||||
submitDisabled={!enabled}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user