mirror of
https://github.com/ansible/awx.git
synced 2026-03-03 09:48:51 -03:30
9
.eslintignore
Normal file
9
.eslintignore
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
jest.*.js
|
||||||
|
webpack.*.js
|
||||||
|
|
||||||
|
etc
|
||||||
|
coverage
|
||||||
|
build
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
images
|
||||||
@@ -7,8 +7,6 @@ import { asyncFlush } from '../jest.setup';
|
|||||||
|
|
||||||
import App from '../src/App';
|
import App from '../src/App';
|
||||||
|
|
||||||
const DEFAULT_ACTIVE_GROUP = 'views_group';
|
|
||||||
|
|
||||||
describe('<App />', () => {
|
describe('<App />', () => {
|
||||||
test('expected content is rendered', () => {
|
test('expected content is rendered', () => {
|
||||||
const appWrapper = mount(
|
const appWrapper = mount(
|
||||||
@@ -60,13 +58,13 @@ describe('<App />', () => {
|
|||||||
const ansible_version = '111';
|
const ansible_version = '111';
|
||||||
const version = '222';
|
const version = '222';
|
||||||
|
|
||||||
const getConfig = jest.fn(() => Promise.resolve({ data: { ansible_version, version} }));
|
const getConfig = jest.fn(() => Promise.resolve({ data: { ansible_version, version } }));
|
||||||
const api = { getConfig };
|
const api = { getConfig };
|
||||||
|
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<App api={api}/>
|
<App api={api} />
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ describe('APIClient (api.js)', () => {
|
|||||||
const mockHttp = ({ post: jest.fn(createPromise) });
|
const mockHttp = ({ post: jest.fn(createPromise) });
|
||||||
|
|
||||||
const api = new APIClient(mockHttp);
|
const api = new APIClient(mockHttp);
|
||||||
const data = { name: 'test '};
|
const data = { name: 'test ' };
|
||||||
await api.createOrganization(data);
|
await api.createOrganization(data);
|
||||||
|
|
||||||
expect(mockHttp.post).toHaveBeenCalledTimes(1);
|
expect(mockHttp.post).toHaveBeenCalledTimes(1);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import React from 'react';
|
|||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import AnsibleSelect from '../../src/components/AnsibleSelect';
|
import AnsibleSelect from '../../src/components/AnsibleSelect';
|
||||||
|
|
||||||
const label = "test select"
|
const label = 'test select';
|
||||||
const mockData = ["/venv/baz/", "/venv/ansible/"];
|
const mockData = ['/venv/baz/', '/venv/ansible/'];
|
||||||
describe('<AnsibleSelect />', () => {
|
describe('<AnsibleSelect />', () => {
|
||||||
test('initially renders succesfully', async () => {
|
test('initially renders succesfully', async () => {
|
||||||
mount(
|
mount(
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
|
|
||||||
import { I18nProvider } from '@lingui/react';
|
|
||||||
import Background from '../../src/components/Background';
|
import Background from '../../src/components/Background';
|
||||||
|
|
||||||
describe('Background', () => {
|
describe('Background', () => {
|
||||||
test('renders the expected content', () => {
|
test('renders the expected content', () => {
|
||||||
const wrapper = mount(<Background><div id="test"/></Background>);
|
const wrapper = mount(<Background><div id="test" /></Background>);
|
||||||
expect(wrapper).toHaveLength(1);
|
expect(wrapper).toHaveLength(1);
|
||||||
expect(wrapper.find('BackgroundImage')).toHaveLength(1);
|
expect(wrapper.find('BackgroundImage')).toHaveLength(1);
|
||||||
expect(wrapper.find('#test')).toHaveLength(1);
|
expect(wrapper.find('#test')).toHaveLength(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ describe('<DataListToolbar />', () => {
|
|||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<DataListToolbar
|
<DataListToolbar
|
||||||
isAllSelected={false}
|
isAllSelected={false}
|
||||||
showExpandCollapse={true}
|
showExpandCollapse
|
||||||
sortedColumnKey="name"
|
sortedColumnKey="name"
|
||||||
sortOrder="ascending"
|
sortOrder="ascending"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import Lookup from '../../src/components/Lookup';
|
|
||||||
import { I18nProvider } from '@lingui/react';
|
import { I18nProvider } from '@lingui/react';
|
||||||
|
import Lookup from '../../src/components/Lookup';
|
||||||
|
|
||||||
const mockData = [{ name: 'foo', id: 0, isChecked: false }];
|
let mockData = [{ name: 'foo', id: 0, isChecked: false }];
|
||||||
describe('<Lookup />', () => {
|
describe('<Lookup />', () => {
|
||||||
test('initially renders succesfully', () => {
|
test('initially renders succesfully', () => {
|
||||||
mount(
|
mount(
|
||||||
@@ -26,7 +26,9 @@ describe('<Lookup />', () => {
|
|||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
expect(spy).not.toHaveBeenCalled();
|
expect(spy).not.toHaveBeenCalled();
|
||||||
wrapper.find('#search').simulate('click');
|
debugger;
|
||||||
|
const searchItem = wrapper.find('.pf-c-input-group__text#search');
|
||||||
|
searchItem.first().simulate('click');
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
test('calls "onChecked" when a user changes a checkbox', () => {
|
test('calls "onChecked" when a user changes a checkbox', () => {
|
||||||
@@ -40,13 +42,15 @@ describe('<Lookup />', () => {
|
|||||||
/>
|
/>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
wrapper.find('#search').simulate('click');
|
debugger;
|
||||||
|
const searchItem = wrapper.find('.pf-c-input-group__text#search');
|
||||||
|
searchItem.first().simulate('click');
|
||||||
wrapper.find('input[type="checkbox"]').simulate('change');
|
wrapper.find('input[type="checkbox"]').simulate('change');
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
test('calls "onRemove" when remove icon is clicked', () => {
|
test('calls "onRemove" when remove icon is clicked', () => {
|
||||||
const spy = jest.spyOn(Lookup.prototype, 'onRemove');
|
const spy = jest.spyOn(Lookup.prototype, 'onRemove');
|
||||||
const mockData = [{ name: 'foo', id: 0, isChecked: false }, { name: 'bar', id: 1, isChecked: true }];
|
mockData = [{ name: 'foo', id: 0, isChecked: false }, { name: 'bar', id: 1, isChecked: true }];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<Lookup
|
<Lookup
|
||||||
@@ -56,12 +60,13 @@ describe('<Lookup />', () => {
|
|||||||
/>
|
/>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
wrapper.find('.awx-c-icon--remove').simulate('click');
|
const removeIcon = wrapper.find('.awx-c-icon--remove').first();
|
||||||
|
removeIcon.simulate('click');
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
test('"wrapTags" method properly handles data', () => {
|
test('"wrapTags" method properly handles data', () => {
|
||||||
const spy = jest.spyOn(Lookup.prototype, 'wrapTags');
|
const spy = jest.spyOn(Lookup.prototype, 'wrapTags');
|
||||||
const mockData = [{ name: 'foo', id: 0, isChecked: false }, { name: 'bar', id: 1, isChecked: false }];
|
mockData = [{ name: 'foo', id: 0, isChecked: false }, { name: 'bar', id: 1, isChecked: false }];
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
<Lookup
|
<Lookup
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ describe('PageHeaderToolbar', () => {
|
|||||||
const pageUserDropdownSelector = 'Dropdown UserIcon';
|
const pageUserDropdownSelector = 'Dropdown UserIcon';
|
||||||
|
|
||||||
test('expected content is rendered on initialization', () => {
|
test('expected content is rendered on initialization', () => {
|
||||||
const wrapper = mount(<I18nProvider><PageHeaderToolbar/></I18nProvider>);
|
const wrapper = mount(<I18nProvider><PageHeaderToolbar /></I18nProvider>);
|
||||||
|
|
||||||
expect(wrapper.find(pageHelpDropdownSelector)).toHaveLength(1);
|
expect(wrapper.find(pageHelpDropdownSelector)).toHaveLength(1);
|
||||||
expect(wrapper.find(pageUserDropdownSelector)).toHaveLength(1);
|
expect(wrapper.find(pageUserDropdownSelector)).toHaveLength(1);
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ describe('<Pagination />', () => {
|
|||||||
pageSizeOptions={[5, 10, 25, 50]}
|
pageSizeOptions={[5, 10, 25, 50]}
|
||||||
onSetPage={onSetPage}
|
onSetPage={onSetPage}
|
||||||
/>
|
/>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ describe('<TowerLogo />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('handles mouse over and out state.hover changes', () => {
|
test('handles mouse over and out state.hover changes', () => {
|
||||||
const onLogoClick = jest.fn();
|
|
||||||
logoWrapper = mount(
|
logoWrapper = mount(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<I18nProvider>
|
<I18nProvider>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { mount } from 'enzyme';
|
|||||||
import { main, getLanguage } from '../src/index';
|
import { main, getLanguage } from '../src/index';
|
||||||
|
|
||||||
const render = template => mount(template);
|
const render = template => mount(template);
|
||||||
const data = { custom_logo: 'foo', custom_login_info: '' }
|
const data = { custom_logo: 'foo', custom_login_info: '' };
|
||||||
|
|
||||||
describe('index.jsx', () => {
|
describe('index.jsx', () => {
|
||||||
test('login loads when unauthenticated', async (done) => {
|
test('login loads when unauthenticated', async (done) => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import OrganizationAdd from '../../../../src/pages/Organizations/screens/OrganizationAdd'
|
import OrganizationAdd from '../../../../src/pages/Organizations/screens/OrganizationAdd';
|
||||||
|
|
||||||
describe('<OrganizationAdd />', () => {
|
describe('<OrganizationAdd />', () => {
|
||||||
test('initially renders succesfully', () => {
|
test('initially renders succesfully', () => {
|
||||||
@@ -57,28 +57,19 @@ describe('<OrganizationAdd />', () => {
|
|||||||
wrapper.find('button.at-C-CancelButton').prop('onClick')();
|
wrapper.find('button.at-C-CancelButton').prop('onClick')();
|
||||||
expect(spy).toBeCalled();
|
expect(spy).toBeCalled();
|
||||||
});
|
});
|
||||||
test('API response data is formatted properly', () => {
|
|
||||||
const mockData = { data: { results: [{ name: 'test instance', id: 1 }] } };
|
|
||||||
const promise = Promise.resolve(mockData);
|
|
||||||
|
|
||||||
return promise.then(({ data }) => {
|
|
||||||
const expected = [{ id: 1, name: 'test instance', isChecked: false }];
|
|
||||||
const results = OrganizationAdd.WrappedComponent.prototype.format(data);
|
|
||||||
expect(results).toEqual(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test('API response is formatted properly', (done) => {
|
test('API response is formatted properly', (done) => {
|
||||||
const spy = jest.spyOn(OrganizationAdd.WrappedComponent.prototype, 'format');
|
const mockedResp = { data: { results: [{ name: 'test instance', id: 1 }] } };
|
||||||
const mockedResp = {data: {id: 1, name: 'foo bar'} };
|
|
||||||
const api = { getInstanceGroups: jest.fn().mockResolvedValue(mockedResp) };
|
const api = { getInstanceGroups: jest.fn().mockResolvedValue(mockedResp) };
|
||||||
mount(
|
const wrapper = mount(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<OrganizationAdd api={api} />
|
<OrganizationAdd api={api} />
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
expect(spy).toHaveBeenCalled();
|
const orgAddElem = wrapper.find('OrganizationAdd');
|
||||||
|
expect([{ id: 1, isChecked: false, name: 'test instance' }]).toEqual(orgAddElem.state().results);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -86,7 +77,7 @@ describe('<OrganizationAdd />', () => {
|
|||||||
test('Successful form submission triggers redirect', (done) => {
|
test('Successful form submission triggers redirect', (done) => {
|
||||||
const onSuccess = jest.spyOn(OrganizationAdd.WrappedComponent.prototype, 'onSuccess');
|
const onSuccess = jest.spyOn(OrganizationAdd.WrappedComponent.prototype, 'onSuccess');
|
||||||
const resetForm = jest.spyOn(OrganizationAdd.WrappedComponent.prototype, 'resetForm');
|
const resetForm = jest.spyOn(OrganizationAdd.WrappedComponent.prototype, 'resetForm');
|
||||||
const mockedResp = {data: {id: 1, related: {instance_groups: '/bar'}}};
|
const mockedResp = { data: { id: 1, related: { instance_groups: '/bar' } } };
|
||||||
const api = { createOrganization: jest.fn().mockResolvedValue(mockedResp), createInstanceGroups: jest.fn().mockResolvedValue('done') };
|
const api = { createOrganization: jest.fn().mockResolvedValue(mockedResp), createInstanceGroups: jest.fn().mockResolvedValue('done') };
|
||||||
const wrapper = mount(
|
const wrapper = mount(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ describe('qs (qs.js)', () => {
|
|||||||
[{ order_by: 'name', page: 1, page_size: 5 }, 'order_by=name&page=1&page_size=5'],
|
[{ order_by: 'name', page: 1, page_size: 5 }, 'order_by=name&page=1&page_size=5'],
|
||||||
[{ '-order_by': 'name', page: '1', page_size: 5 }, '-order_by=name&page=1&page_size=5'],
|
[{ '-order_by': 'name', page: '1', page_size: 5 }, '-order_by=name&page=1&page_size=5'],
|
||||||
]
|
]
|
||||||
.forEach(([params, expectedQueryString]) => {
|
.forEach(([params, expectedQueryString]) => {
|
||||||
const actualQueryString = encodeQueryString(params);
|
const actualQueryString = encodeQueryString(params);
|
||||||
|
|
||||||
expect(actualQueryString).toEqual(expectedQueryString);
|
expect(actualQueryString).toEqual(expectedQueryString);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('parseQueryString returns the expected queryParams', () => {
|
test('parseQueryString returns the expected queryParams', () => {
|
||||||
@@ -20,10 +20,10 @@ describe('qs (qs.js)', () => {
|
|||||||
['order_by=name&page=1&page_size=5', ['page', 'page_size'], { order_by: 'name', page: 1, page_size: 5 }],
|
['order_by=name&page=1&page_size=5', ['page', 'page_size'], { order_by: 'name', page: 1, page_size: 5 }],
|
||||||
['order_by=name&page=1&page_size=5', ['page_size'], { order_by: 'name', page: '1', page_size: 5 }],
|
['order_by=name&page=1&page_size=5', ['page_size'], { order_by: 'name', page: '1', page_size: 5 }],
|
||||||
]
|
]
|
||||||
.forEach(([queryString, integerFields, expectedQueryParams]) => {
|
.forEach(([queryString, integerFields, expectedQueryParams]) => {
|
||||||
const actualQueryParams = parseQueryString(queryString, integerFields);
|
const actualQueryParams = parseQueryString(queryString, integerFields);
|
||||||
|
|
||||||
expect(actualQueryParams).toEqual(expectedQueryParams)
|
expect(actualQueryParams).toEqual(expectedQueryParams);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack-dev-server --config ./webpack.config.js --mode development",
|
"start": "webpack-dev-server --config ./webpack.config.js --mode development",
|
||||||
"test": "jest --watch --coverage",
|
"test": "jest --watch --coverage",
|
||||||
"lint": "./node_modules/eslint/bin/eslint.js src/**/*.js src/**/*.jsx",
|
"lint": "eslint --ext .js --ext .jsx .",
|
||||||
"add-locale": "lingui add-locale",
|
"add-locale": "lingui add-locale",
|
||||||
"extract-strings": "lingui extract",
|
"extract-strings": "lingui extract",
|
||||||
"compile-strings": "lingui compile"
|
"compile-strings": "lingui compile"
|
||||||
|
|||||||
36
src/App.jsx
36
src/App.jsx
@@ -35,28 +35,17 @@ class App extends Component {
|
|||||||
this.onAboutModalClose = this.onAboutModalClose.bind(this);
|
this.onAboutModalClose = this.onAboutModalClose.bind(this);
|
||||||
this.onAboutModalOpen = this.onAboutModalOpen.bind(this);
|
this.onAboutModalOpen = this.onAboutModalOpen.bind(this);
|
||||||
this.onNavToggle = this.onNavToggle.bind(this);
|
this.onNavToggle = this.onNavToggle.bind(this);
|
||||||
};
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
this.fetchConfig();
|
this.fetchConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchConfig () {
|
|
||||||
const { api } = this.props;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { data: { ansible_version, custom_virtualenvs, version } } = await api.getConfig();
|
|
||||||
this.setState({ ansible_version, custom_virtualenvs, version });
|
|
||||||
} catch (err) {
|
|
||||||
this.setState({ ansible_version: null, custom_virtualenvs: null, version: null });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async onLogout () {
|
async onLogout () {
|
||||||
const { api } = this.props;
|
const { api } = this.props;
|
||||||
|
|
||||||
await api.logout();
|
await api.logout();
|
||||||
window.location.replace('/#/login')
|
window.location.replace('/#/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
onAboutModalOpen () {
|
onAboutModalOpen () {
|
||||||
@@ -71,6 +60,17 @@ class App extends Component {
|
|||||||
this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen }));
|
this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchConfig () {
|
||||||
|
const { api } = this.props;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data: { ansible_version, custom_virtualenvs, version } } = await api.getConfig();
|
||||||
|
this.setState({ ansible_version, custom_virtualenvs, version });
|
||||||
|
} catch (err) {
|
||||||
|
this.setState({ ansible_version: null, custom_virtualenvs: null, version: null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
ansible_version,
|
ansible_version,
|
||||||
@@ -100,17 +100,17 @@ class App extends Component {
|
|||||||
<PageHeader
|
<PageHeader
|
||||||
showNavToggle
|
showNavToggle
|
||||||
onNavToggle={this.onNavToggle}
|
onNavToggle={this.onNavToggle}
|
||||||
logo={<TowerLogo linkTo="/"/>}
|
logo={<TowerLogo linkTo="/" />}
|
||||||
toolbar={
|
toolbar={(
|
||||||
<PageHeaderToolbar
|
<PageHeaderToolbar
|
||||||
isAboutDisabled={!version}
|
isAboutDisabled={!version}
|
||||||
onAboutClick={this.onAboutModalOpen}
|
onAboutClick={this.onAboutModalOpen}
|
||||||
onLogoutClick={this.onLogout}
|
onLogoutClick={this.onLogout}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
sidebar={
|
sidebar={(
|
||||||
<PageSidebar
|
<PageSidebar
|
||||||
isNavOpen={isNavOpen}
|
isNavOpen={isNavOpen}
|
||||||
nav={(
|
nav={(
|
||||||
@@ -128,7 +128,7 @@ class App extends Component {
|
|||||||
</Nav>
|
</Nav>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
>
|
||||||
<ConfigContext.Provider value={config}>
|
<ConfigContext.Provider value={config}>
|
||||||
{render && render({ routeGroups })}
|
{render && render({ routeGroups })}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
class AnsibleSelect extends React.Component {
|
class AnsibleSelect extends React.Component {
|
||||||
constructor(props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.onSelectChange = this.onSelectChange.bind(this);
|
this.onSelectChange = this.onSelectChange.bind(this);
|
||||||
}
|
}
|
||||||
@@ -16,34 +16,39 @@ class AnsibleSelect extends React.Component {
|
|||||||
count: 1,
|
count: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDerivedStateFromProps(nexProps, _) {
|
static getDerivedStateFromProps (nexProps) {
|
||||||
if (nexProps.data) {
|
if (nexProps.data) {
|
||||||
return {
|
return {
|
||||||
count: nexProps.data.length,
|
count: nexProps.data.length,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
onSelectChange(val, _) {
|
|
||||||
this.props.selectChange(val);
|
onSelectChange (val) {
|
||||||
|
const { selectChange } = this.props;
|
||||||
|
selectChange(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render () {
|
||||||
const { count } = this.state;
|
const { count } = this.state;
|
||||||
|
const { labelName, selected, data } = this.props;
|
||||||
|
let elem;
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
return (
|
elem = (
|
||||||
<FormGroup label={this.props.labelName} fieldId="ansible-select">
|
<FormGroup label={labelName} fieldId="ansible-select">
|
||||||
<Select value={this.props.selected} onChange={this.onSelectChange} aria-label="Select Input">
|
<Select value={selected} onChange={this.onSelectChange} aria-label="Select Input">
|
||||||
{this.props.data.map((datum, index) => (
|
{data.map((datum) => (
|
||||||
<SelectOption isDisabled={datum.disabled} key={index} value={datum} label={datum} />
|
<SelectOption isDisabled={datum.disabled} key={datum} value={datum} label={datum} />
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
)
|
);
|
||||||
}
|
} else {
|
||||||
else {
|
elem = null;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return elem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,10 +53,6 @@ class DataListToolbar extends React.Component {
|
|||||||
this.onSort = this.onSort.bind(this);
|
this.onSort = this.onSort.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSearchInputChange (searchValue) {
|
|
||||||
this.setState({ searchValue });
|
|
||||||
}
|
|
||||||
|
|
||||||
onSortDropdownToggle (isSortDropdownOpen) {
|
onSortDropdownToggle (isSortDropdownOpen) {
|
||||||
this.setState({ isSortDropdownOpen });
|
this.setState({ isSortDropdownOpen });
|
||||||
}
|
}
|
||||||
@@ -97,6 +93,10 @@ class DataListToolbar extends React.Component {
|
|||||||
onSort(sortedColumnKey, newSortOrder);
|
onSort(sortedColumnKey, newSortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSearchInputChange (searchValue) {
|
||||||
|
this.setState({ searchValue });
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { up } = DropdownPosition;
|
const { up } = DropdownPosition;
|
||||||
const {
|
const {
|
||||||
@@ -223,7 +223,7 @@ class DataListToolbar extends React.Component {
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
aria-label={i18n._(t`Sort`)}
|
aria-label={i18n._(t`Sort`)}
|
||||||
>
|
>
|
||||||
<SortIcon/>
|
<SortIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</ToolbarItem>
|
</ToolbarItem>
|
||||||
</ToolbarGroup>
|
</ToolbarGroup>
|
||||||
|
|||||||
@@ -11,24 +11,24 @@ export default ({
|
|||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
}) => (
|
}) => (
|
||||||
<li key={itemId} className="pf-c-data-list__item" aria-labelledby="check-action-item1">
|
<li key={itemId} className="pf-c-data-list__item" aria-labelledby="check-action-item1">
|
||||||
<div className="pf-c-data-list__check">
|
<div className="pf-c-data-list__check">
|
||||||
<I18n>
|
<I18n>
|
||||||
{({ i18n }) => (
|
{({ i18n }) => (
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={isSelected}
|
checked={isSelected}
|
||||||
onChange={onSelect}
|
onChange={onSelect}
|
||||||
aria-label={i18n._(t`selected ${itemId}`)}
|
aria-label={i18n._(t`selected ${itemId}`)}
|
||||||
id={`selectd-${itemId}`}
|
id={`selectd-${itemId}`}
|
||||||
value={itemId}
|
value={itemId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</I18n>
|
</I18n>
|
||||||
</div>
|
</div>
|
||||||
<div className="pf-c-data-list__cell">
|
<div className="pf-c-data-list__cell">
|
||||||
<label htmlFor={`selectd-${itemId}`} className="check-action-item">
|
<label htmlFor={`selectd-${itemId}`} className="check-action-item">
|
||||||
<b>{name}</b>
|
<b>{name}</b>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ import {
|
|||||||
ToolbarGroup,
|
ToolbarGroup,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
|
|
||||||
import CheckboxListItem from '../ListItem'
|
import CheckboxListItem from '../ListItem';
|
||||||
|
|
||||||
class Lookup extends React.Component {
|
class Lookup extends React.Component {
|
||||||
constructor(props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
isModalOpen: false,
|
isModalOpen: false,
|
||||||
}
|
};
|
||||||
this.handleModalToggle = this.handleModalToggle.bind(this);
|
this.handleModalToggle = this.handleModalToggle.bind(this);
|
||||||
this.onLookup = this.onLookup.bind(this);
|
this.onLookup = this.onLookup.bind(this);
|
||||||
this.onChecked = this.onChecked.bind(this);
|
this.onChecked = this.onChecked.bind(this);
|
||||||
@@ -24,46 +24,54 @@ class Lookup extends React.Component {
|
|||||||
this.onRemove = this.onRemove.bind(this);
|
this.onRemove = this.onRemove.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleModalToggle() {
|
onLookup () {
|
||||||
this.setState((prevState, _) => ({
|
|
||||||
isModalOpen: !prevState.isModalOpen,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
onLookup() {
|
|
||||||
this.handleModalToggle();
|
this.handleModalToggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
onChecked(_, evt) {
|
onChecked (_, evt) {
|
||||||
this.props.lookupChange(evt.target.value);
|
const { lookupChange } = this.props;
|
||||||
};
|
lookupChange(evt.target.value);
|
||||||
|
|
||||||
onRemove(evt) {
|
|
||||||
this.props.lookupChange(evt.target.id);
|
|
||||||
}
|
|
||||||
wrapTags(tags) {
|
|
||||||
return tags.filter(tag => tag.isChecked).map((tag, index) => {
|
|
||||||
return (
|
|
||||||
<span className="awx-c-tag--pill" key={index}>{tag.name}<span className="awx-c-icon--remove" id={tag.id} onClick={this.onRemove}>x</span></span>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
onRemove (evt) {
|
||||||
|
const { lookupChange } = this.props;
|
||||||
|
lookupChange(evt.target.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleModalToggle () {
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
isModalOpen: !prevState.isModalOpen,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapTags (tags) {
|
||||||
|
return tags.filter(tag => tag.isChecked).map((tag) => (
|
||||||
|
<span className="awx-c-tag--pill" key={tag.id}>
|
||||||
|
{tag.name}
|
||||||
|
<Button className="awx-c-icon--remove" id={tag.id} onClick={this.onRemove}>
|
||||||
|
x
|
||||||
|
</Button>
|
||||||
|
</span>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
const { isModalOpen } = this.state;
|
const { isModalOpen } = this.state;
|
||||||
const { data } = this.props;
|
const { data, lookupHeader } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="pf-c-input-group awx-lookup">
|
<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>
|
<Button className="pf-c-input-group__text" aria-label="search" id="search" onClick={this.onLookup}>
|
||||||
<div className="pf-c-form-control">{this.wrapTags(this.props.data)}</div>
|
<SearchIcon />
|
||||||
|
</Button>
|
||||||
|
<div className="pf-c-form-control">{this.wrapTags(data)}</div>
|
||||||
<Modal
|
<Modal
|
||||||
className="awx-c-modal"
|
className="awx-c-modal"
|
||||||
title={`Select ${this.props.lookupHeader}`}
|
title={`Select ${lookupHeader}`}
|
||||||
isOpen={isModalOpen}
|
isOpen={isModalOpen}
|
||||||
onClose={this.handleModalToggle}
|
onClose={this.handleModalToggle}
|
||||||
>
|
>
|
||||||
<ul className="pf-c-data-list awx-c-list">
|
<ul className="pf-c-data-list awx-c-list">
|
||||||
{data.map(i =>
|
{data.map(i => (
|
||||||
<CheckboxListItem
|
<CheckboxListItem
|
||||||
key={i.id}
|
key={i.id}
|
||||||
itemId={i.id}
|
itemId={i.id}
|
||||||
@@ -71,12 +79,12 @@ class Lookup extends React.Component {
|
|||||||
isSelected={i.isChecked}
|
isSelected={i.isChecked}
|
||||||
onSelect={this.onChecked}
|
onSelect={this.onChecked}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<ActionGroup className="at-align-right">
|
<ActionGroup className="at-align-right">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarGroup>
|
<ToolbarGroup>
|
||||||
<Button className="at-C-SubmitButton" variant="primary" onClick={this.handleModalToggle} >Select</Button>
|
<Button className="at-C-SubmitButton" variant="primary" onClick={this.handleModalToggle}>Select</Button>
|
||||||
</ToolbarGroup>
|
</ToolbarGroup>
|
||||||
<ToolbarGroup>
|
<ToolbarGroup>
|
||||||
<Button className="at-C-CancelButton" variant="secondary" onClick={this.handleModalToggle}>Cancel</Button>
|
<Button className="at-C-CancelButton" variant="secondary" onClick={this.handleModalToggle}>Cancel</Button>
|
||||||
@@ -85,7 +93,7 @@ class Lookup extends React.Component {
|
|||||||
</ActionGroup>
|
</ActionGroup>
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default Lookup;
|
export default Lookup;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class Pagination extends Component {
|
|||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-bitwise
|
||||||
const isPositiveInteger = value >>> 0 === parseFloat(value) && parseInt(value, 10) > 0;
|
const isPositiveInteger = value >>> 0 === parseFloat(value) && parseInt(value, 10) > 0;
|
||||||
const isValid = isPositiveInteger && parseInt(value, 10) <= pageCount;
|
const isValid = isPositiveInteger && parseInt(value, 10) <= pageCount;
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ class Pagination extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onNext () {
|
onNext () {
|
||||||
const { onSetPage, page, pageCount, page_size } = this.props;
|
const { onSetPage, page, page_size } = this.props;
|
||||||
const nextPage = page + 1;
|
const nextPage = page + 1;
|
||||||
|
|
||||||
onSetPage(nextPage, page_size);
|
onSetPage(nextPage, page_size);
|
||||||
@@ -82,7 +83,7 @@ class Pagination extends Component {
|
|||||||
onLast () {
|
onLast () {
|
||||||
const { onSetPage, pageCount, page_size } = this.props;
|
const { onSetPage, pageCount, page_size } = this.props;
|
||||||
|
|
||||||
onSetPage(pageCount, page_size)
|
onSetPage(pageCount, page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
onTogglePageSize (isOpen) {
|
onTogglePageSize (isOpen) {
|
||||||
@@ -160,7 +161,7 @@ class Pagination extends Component {
|
|||||||
<LevelItem>
|
<LevelItem>
|
||||||
<Split gutter="md" className="pf-u-display-flex pf-u-align-items-center">
|
<Split gutter="md" className="pf-u-display-flex pf-u-align-items-center">
|
||||||
<SplitItem>
|
<SplitItem>
|
||||||
<Trans>{itemMin} - {itemMax} of {count}</Trans>
|
<Trans>{`${itemMin} - ${itemMax} of ${count}`}</Trans>
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
<SplitItem>
|
<SplitItem>
|
||||||
<div className="pf-c-input-group">
|
<div className="pf-c-input-group">
|
||||||
@@ -187,7 +188,8 @@ class Pagination extends Component {
|
|||||||
<SplitItem isMain>
|
<SplitItem isMain>
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
<Trans>
|
<Trans>
|
||||||
Page <TextInput
|
{'Page '}
|
||||||
|
<TextInput
|
||||||
isDisabled={pageCount === 1}
|
isDisabled={pageCount === 1}
|
||||||
aria-label={i18n._(t`Page Number`)}
|
aria-label={i18n._(t`Page Number`)}
|
||||||
style={{
|
style={{
|
||||||
@@ -201,7 +203,9 @@ class Pagination extends Component {
|
|||||||
value={value}
|
value={value}
|
||||||
type="text"
|
type="text"
|
||||||
onChange={this.onPageChange}
|
onChange={this.onPageChange}
|
||||||
/> of {pageCount}
|
/>
|
||||||
|
{' of '}
|
||||||
|
{pageCount}
|
||||||
</Trans>
|
</Trans>
|
||||||
</form>
|
</form>
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
import './tabs.scss';
|
import './tabs.scss';
|
||||||
|
|
||||||
|
|
||||||
const Tab = ({ location, match, tab, currentTab, children, breadcrumb }) => {
|
const Tab = ({ location, match, tab, currentTab, children, breadcrumb }) => {
|
||||||
const tabClasses = () => {
|
const tabClasses = () => {
|
||||||
let classes = 'pf-c-tabs__item';
|
let classes = 'pf-c-tabs__item';
|
||||||
@@ -28,13 +27,14 @@ const Tab = ({ location, match, tab, currentTab, children, breadcrumb }) => {
|
|||||||
return (
|
return (
|
||||||
<li className={tabClasses()}>
|
<li className={tabClasses()}>
|
||||||
<Link
|
<Link
|
||||||
className={'pf-c-tabs__button'}
|
className="pf-c-tabs__button"
|
||||||
to={{ pathname: `${match.url}`, search: tabParams(), state: { breadcrumb } }}
|
to={{ pathname: `${match.url}`, search: tabParams(), state: { breadcrumb } }}
|
||||||
replace={tab === currentTab}>
|
replace={tab === currentTab}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Tab;
|
export default Tab;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './tabs.scss';
|
import './tabs.scss';
|
||||||
|
|
||||||
|
|
||||||
const Tabs = ({ children, labelText }) => (
|
const Tabs = ({ children, labelText }) => (
|
||||||
<div className="pf-c-tabs" aria-label={labelText}>
|
<div className="pf-c-tabs" aria-label={labelText}>
|
||||||
<ul className="pf-c-tabs__list">
|
<ul className="pf-c-tabs__list">
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
export const ConfigContext = React.createContext({});
|
export const ConfigContext = React.createContext({});
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export function getLanguage (nav) {
|
|||||||
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
|
const languageWithoutRegionCode = language.toLowerCase().split(/[_-]+/)[0];
|
||||||
|
|
||||||
return languageWithoutRegionCode;
|
return languageWithoutRegionCode;
|
||||||
};
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Function Main
|
// Function Main
|
||||||
@@ -269,7 +269,7 @@ export async function main (render, api) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -280,7 +280,8 @@ export async function main (render, api) {
|
|||||||
)}
|
)}
|
||||||
</I18n>
|
</I18n>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</HashRouter>, el);
|
</HashRouter>, el
|
||||||
};
|
);
|
||||||
|
}
|
||||||
|
|
||||||
main(ReactDOM.render, new APIClient(http));
|
main(ReactDOM.render, new APIClient(http));
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ const OrganizationBreadcrumb = ({ parentObj, organization, currentTab, location
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
breadcrumb = (
|
breadcrumb = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{generateCrumb(true)}
|
{generateCrumb(true)}
|
||||||
|
|||||||
@@ -8,18 +8,15 @@ import {
|
|||||||
Link
|
Link
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
const OrganizationEdit = ({ match, parentBreadcrumbObj, organization }) => {
|
const OrganizationEdit = ({ match, parentBreadcrumbObj, organization }) => (
|
||||||
|
<Card className="at-c-orgPane">
|
||||||
return (
|
<CardBody>
|
||||||
<Card className="at-c-orgPane">
|
<Trans>edit view </Trans>
|
||||||
<CardBody>
|
<Link to={{ pathname: `/organizations/${match.params.id}`, state: { breadcrumb: parentBreadcrumbObj, organization } }}>
|
||||||
<Trans>edit view </Trans>
|
<Trans>save/cancel and go back to view</Trans>
|
||||||
<Link to={{ pathname: `/organizations/${match.params.id}`, state: { breadcrumb: parentBreadcrumbObj, organization } }}>
|
</Link>
|
||||||
<Trans>save/cancel and go back to view</Trans>
|
</CardBody>
|
||||||
</Link>
|
</Card>
|
||||||
</CardBody>
|
);
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default OrganizationEdit;
|
export default OrganizationEdit;
|
||||||
|
|||||||
@@ -20,10 +20,21 @@ import {
|
|||||||
|
|
||||||
import { ConfigContext } from '../../../context';
|
import { ConfigContext } from '../../../context';
|
||||||
import Lookup from '../../../components/Lookup';
|
import Lookup from '../../../components/Lookup';
|
||||||
import AnsibleSelect from '../../../components/AnsibleSelect'
|
import AnsibleSelect from '../../../components/AnsibleSelect';
|
||||||
|
|
||||||
const { light } = PageSectionVariants;
|
const { light } = PageSectionVariants;
|
||||||
|
|
||||||
|
const format = (data) => {
|
||||||
|
const results = data.results.map((result) => ({
|
||||||
|
id: result.id,
|
||||||
|
name: result.name,
|
||||||
|
isChecked: false
|
||||||
|
}));
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
class OrganizationAdd extends React.Component {
|
class OrganizationAdd extends React.Component {
|
||||||
constructor(props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.handleChange = this.handleChange.bind(this);
|
this.handleChange = this.handleChange.bind(this);
|
||||||
@@ -33,7 +44,6 @@ class OrganizationAdd extends React.Component {
|
|||||||
this.resetForm = this.resetForm.bind(this);
|
this.resetForm = this.resetForm.bind(this);
|
||||||
this.onSuccess = this.onSuccess.bind(this);
|
this.onSuccess = this.onSuccess.bind(this);
|
||||||
this.onCancel = this.onCancel.bind(this);
|
this.onCancel = this.onCancel.bind(this);
|
||||||
this.format = this.format.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@@ -45,87 +55,80 @@ class OrganizationAdd extends React.Component {
|
|||||||
error: '',
|
error: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
onSelectChange(value, _) {
|
async componentDidMount () {
|
||||||
this.setState({ custom_virtualenv: value });
|
const { api } = this.props;
|
||||||
};
|
try {
|
||||||
|
const { data } = await api.getInstanceGroups();
|
||||||
|
const results = format(data);
|
||||||
|
this.setState({ results });
|
||||||
|
} catch (error) {
|
||||||
|
this.setState({ getInstanceGroupsError: error });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onLookupChange(id, _) {
|
onSelectChange (value) {
|
||||||
let selected = { ...this.state.results }
|
this.setState({ custom_virtualenv: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
onLookupChange (id) {
|
||||||
|
const { results } = this.state;
|
||||||
|
const selected = { ...results };
|
||||||
const index = id - 1;
|
const index = id - 1;
|
||||||
selected[index].isChecked = !selected[index].isChecked;
|
selected[index].isChecked = !selected[index].isChecked;
|
||||||
this.setState({ selected })
|
this.setState({ selected });
|
||||||
}
|
}
|
||||||
|
|
||||||
resetForm() {
|
async onSubmit () {
|
||||||
this.setState({
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
});
|
|
||||||
let reset = [];
|
|
||||||
this.state.results.map((result) => {
|
|
||||||
reset.push({ id: result.id, name: result.name, isChecked: false });
|
|
||||||
})
|
|
||||||
this.setState({ results: reset });
|
|
||||||
}
|
|
||||||
|
|
||||||
handleChange(_, evt) {
|
|
||||||
this.setState({ [evt.target.name]: evt.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
async onSubmit() {
|
|
||||||
const { api } = this.props;
|
const { api } = this.props;
|
||||||
const data = Object.assign({}, { ...this.state });
|
const data = Object.assign({}, { ...this.state });
|
||||||
|
const { results } = this.state;
|
||||||
try {
|
try {
|
||||||
const { data: response } = await api.createOrganization(data);
|
const { data: response } = await api.createOrganization(data);
|
||||||
const url = response.related.instance_groups;
|
const url = response.related.instance_groups;
|
||||||
const selected = this.state.results.filter(group => group.isChecked);
|
const selected = results.filter(group => group.isChecked);
|
||||||
try {
|
try {
|
||||||
if (selected.length > 0) {
|
if (selected.length > 0) {
|
||||||
selected.forEach( async (select) => {
|
selected.forEach(async (select) => {
|
||||||
await api.createInstanceGroups(url, select.id);
|
await api.createInstanceGroups(url, select.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({ createInstanceGroupsError: err })
|
this.setState({ createInstanceGroupsError: err });
|
||||||
} finally {
|
} finally {
|
||||||
this.resetForm();
|
this.resetForm();
|
||||||
this.onSuccess(response.id);
|
this.onSuccess(response.id);
|
||||||
}
|
}
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
this.setState({ onSubmitError: err });
|
||||||
this.setState({ onSubmitError: err })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onCancel() {
|
onCancel () {
|
||||||
this.props.history.push('/organizations');
|
const { history } = this.props;
|
||||||
|
history.push('/organizations');
|
||||||
}
|
}
|
||||||
|
|
||||||
onSuccess(id) {
|
onSuccess (id) {
|
||||||
this.props.history.push(`/organizations/${id}`);
|
const { history } = this.props;
|
||||||
|
history.push(`/organizations/${id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
format(data) {
|
handleChange (_, evt) {
|
||||||
let results = [];
|
this.setState({ [evt.target.name]: evt.target.value });
|
||||||
data.results.map((result) => {
|
}
|
||||||
results.push({ id: result.id, name: result.name, isChecked: false });
|
|
||||||
|
resetForm () {
|
||||||
|
this.setState({
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
});
|
});
|
||||||
return results;
|
const { results } = this.state;
|
||||||
};
|
const reset = results.map((result) => ({ id: result.id, name: result.name, isChecked: false }));
|
||||||
|
this.setState({ results: reset });
|
||||||
async componentDidMount() {
|
|
||||||
const { api } = this.props;
|
|
||||||
try {
|
|
||||||
const { data } = await api.getInstanceGroups();
|
|
||||||
const results = this.format(data);
|
|
||||||
this.setState({ results });
|
|
||||||
} catch (error) {
|
|
||||||
this.setState({ getInstanceGroupsError: error })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render () {
|
||||||
const { name, results } = this.state;
|
const { name, results, description, custom_virtualenv } = this.state;
|
||||||
const enabled = name.length > 0; // TODO: add better form validation
|
const enabled = name.length > 0; // TODO: add better form validation
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -150,7 +153,7 @@ class OrganizationAdd extends React.Component {
|
|||||||
type="text"
|
type="text"
|
||||||
id="add-org-form-name"
|
id="add-org-form-name"
|
||||||
name="name"
|
name="name"
|
||||||
value={this.state.name}
|
value={name}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@@ -158,7 +161,7 @@ class OrganizationAdd extends React.Component {
|
|||||||
<TextInput
|
<TextInput
|
||||||
id="add-org-form-description"
|
id="add-org-form-description"
|
||||||
name="description"
|
name="description"
|
||||||
value={this.state.description}
|
value={description}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
@@ -170,14 +173,14 @@ class OrganizationAdd extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<ConfigContext.Consumer>
|
<ConfigContext.Consumer>
|
||||||
{({ custom_virtualenvs }) =>
|
{({ custom_virtualenvs }) => (
|
||||||
<AnsibleSelect
|
<AnsibleSelect
|
||||||
labelName="Ansible Environment"
|
labelName="Ansible Environment"
|
||||||
selected={this.state.custom_virtualenv}
|
selected={custom_virtualenv}
|
||||||
selectChange={this.onSelectChange}
|
selectChange={this.onSelectChange}
|
||||||
data={custom_virtualenvs}
|
data={custom_virtualenvs}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
</ConfigContext.Consumer>
|
</ConfigContext.Consumer>
|
||||||
</Gallery>
|
</Gallery>
|
||||||
<ActionGroup className="at-align-right">
|
<ActionGroup className="at-align-right">
|
||||||
@@ -200,7 +203,7 @@ class OrganizationAdd extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OrganizationAdd.contextTypes = {
|
OrganizationAdd.contextTypes = {
|
||||||
custom_virtualenvs: PropTypes.array,
|
custom_virtualenvs: PropTypes.arrayOf(PropTypes.string)
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withRouter(OrganizationAdd);
|
export default withRouter(OrganizationAdd);
|
||||||
|
|||||||
Reference in New Issue
Block a user