mirror of
https://github.com/ansible/awx.git
synced 2026-01-16 20:30:46 -03:30
Merge pull request #6109 from marshmalien/inventory-host-toggle
Use HostToggle component in InventoryHostList Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
commit
33df6f8ad2
1
awx/ui_next/src/components/HostToggle/index.js
Normal file
1
awx/ui_next/src/components/HostToggle/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './HostToggle';
|
||||
@ -12,7 +12,7 @@ import { VariablesDetail } from '@components/CodeMirrorInput';
|
||||
import Sparkline from '@components/Sparkline';
|
||||
import DeleteButton from '@components/DeleteButton';
|
||||
import { HostsAPI } from '@api';
|
||||
import HostToggle from '../shared/HostToggle';
|
||||
import HostToggle from '@components/HostToggle';
|
||||
|
||||
function HostDetail({ host, i18n, onUpdateHost }) {
|
||||
const {
|
||||
|
||||
@ -121,7 +121,7 @@ describe('<HostList />', () => {
|
||||
expect(wrapper.find('HostListItem')).toHaveLength(3);
|
||||
});
|
||||
|
||||
test('should select single item', async () => {
|
||||
test('should select and deselect a single item', async () => {
|
||||
let wrapper;
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(<HostList />);
|
||||
@ -141,6 +141,19 @@ describe('<HostList />', () => {
|
||||
.first()
|
||||
.prop('isSelected')
|
||||
).toEqual(true);
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('input#select-host-1')
|
||||
.closest('DataListCheck')
|
||||
.invoke('onChange')();
|
||||
});
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper
|
||||
.find('HostListItem')
|
||||
.first()
|
||||
.prop('isSelected')
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
test('should select all items', async () => {
|
||||
|
||||
@ -18,7 +18,7 @@ import { PencilAltIcon } from '@patternfly/react-icons';
|
||||
import Sparkline from '@components/Sparkline';
|
||||
import { Host } from '@types';
|
||||
import styled from 'styled-components';
|
||||
import HostToggle from '../shared/HostToggle';
|
||||
import HostToggle from '@components/HostToggle';
|
||||
|
||||
const DataListAction = styled(_DataListAction)`
|
||||
align-items: center;
|
||||
|
||||
@ -3,8 +3,6 @@ import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||
|
||||
import HostsListItem from './HostListItem';
|
||||
|
||||
const onToggleHost = jest.fn();
|
||||
|
||||
const mockHost = {
|
||||
id: 1,
|
||||
name: 'Host 1',
|
||||
@ -32,13 +30,12 @@ describe('<HostsListItem />', () => {
|
||||
detailUrl="/host/1"
|
||||
onSelect={() => {}}
|
||||
host={mockHost}
|
||||
onToggleHost={onToggleHost}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('edit button shown to users with edit capabilities', () => {
|
||||
@ -54,7 +51,6 @@ describe('<HostsListItem />', () => {
|
||||
detailUrl="/host/1"
|
||||
onSelect={() => {}}
|
||||
host={copyMockHost}
|
||||
onToggleHost={onToggleHost}
|
||||
/>
|
||||
);
|
||||
expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy();
|
||||
|
||||
@ -10,11 +10,11 @@ import {
|
||||
DataListItem,
|
||||
DataListItemCells,
|
||||
DataListItemRow,
|
||||
Switch,
|
||||
Tooltip,
|
||||
} from '@patternfly/react-core';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||
import HostToggle from '@components/HostToggle';
|
||||
import Sparkline from '@components/Sparkline';
|
||||
import { Host } from '@types';
|
||||
import styled from 'styled-components';
|
||||
@ -27,16 +27,7 @@ const DataListAction = styled(_DataListAction)`
|
||||
`;
|
||||
|
||||
function InventoryHostItem(props) {
|
||||
const {
|
||||
detailUrl,
|
||||
editUrl,
|
||||
host,
|
||||
i18n,
|
||||
isSelected,
|
||||
onSelect,
|
||||
toggleHost,
|
||||
toggleLoading,
|
||||
} = props;
|
||||
const { detailUrl, editUrl, host, i18n, isSelected, onSelect } = props;
|
||||
|
||||
const recentPlaybookJobs = host.summary_fields.recent_jobs.map(job => ({
|
||||
...job,
|
||||
@ -71,27 +62,7 @@ function InventoryHostItem(props) {
|
||||
aria-labelledby={labelId}
|
||||
id={labelId}
|
||||
>
|
||||
<Tooltip
|
||||
content={i18n._(
|
||||
t`Indicates if a host is available and should be included
|
||||
in running jobs. For hosts that are part of an external
|
||||
inventory, this may be reset by the inventory sync process.`
|
||||
)}
|
||||
position="top"
|
||||
>
|
||||
<Switch
|
||||
css="display: inline-flex;"
|
||||
id={`host-${host.id}-toggle`}
|
||||
label={i18n._(t`On`)}
|
||||
labelOff={i18n._(t`Off`)}
|
||||
isChecked={host.enabled}
|
||||
isDisabled={
|
||||
toggleLoading || !host.summary_fields.user_capabilities?.edit
|
||||
}
|
||||
onChange={() => toggleHost(host)}
|
||||
aria-label={i18n._(t`Toggle host`)}
|
||||
/>
|
||||
</Tooltip>
|
||||
<HostToggle host={host} />
|
||||
{host.summary_fields.user_capabilities?.edit && (
|
||||
<Tooltip content={i18n._(t`Edit Host`)} position="top">
|
||||
<Button variant="plain" component={Link} to={`${editUrl}`}>
|
||||
@ -110,8 +81,6 @@ InventoryHostItem.propTypes = {
|
||||
host: Host.isRequired,
|
||||
isSelected: bool.isRequired,
|
||||
onSelect: func.isRequired,
|
||||
toggleHost: func.isRequired,
|
||||
toggleLoading: bool.isRequired,
|
||||
};
|
||||
|
||||
export default withI18n()(InventoryHostItem);
|
||||
|
||||
@ -2,8 +2,6 @@ import React from 'react';
|
||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||
import InventoryHostItem from './InventoryHostItem';
|
||||
|
||||
let toggleHost;
|
||||
|
||||
const mockHost = {
|
||||
id: 1,
|
||||
name: 'Host 1',
|
||||
@ -17,65 +15,54 @@ const mockHost = {
|
||||
user_capabilities: {
|
||||
edit: true,
|
||||
},
|
||||
recent_jobs: [],
|
||||
recent_jobs: [
|
||||
{
|
||||
id: 123,
|
||||
name: 'Demo Job Template',
|
||||
status: 'failed',
|
||||
finished: '2020-02-26T22:38:41.037991Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
describe('<InventoryHostItem />', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
toggleHost = jest.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('edit button shown to users with edit capabilities', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
wrapper = mountWithContexts(
|
||||
<InventoryHostItem
|
||||
isSelected={false}
|
||||
detailUrl="/host/1"
|
||||
onSelect={() => {}}
|
||||
host={mockHost}
|
||||
toggleHost={toggleHost}
|
||||
toggleLoading={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('edit button shown to users with edit capabilities', () => {
|
||||
expect(wrapper.find('PencilAltIcon').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('edit button hidden from users without edit capabilities', () => {
|
||||
const copyMockHost = Object.assign({}, mockHost);
|
||||
copyMockHost.summary_fields.user_capabilities.edit = false;
|
||||
const wrapper = mountWithContexts(
|
||||
wrapper = mountWithContexts(
|
||||
<InventoryHostItem
|
||||
isSelected={false}
|
||||
detailUrl="/host/1"
|
||||
onSelect={() => {}}
|
||||
host={copyMockHost}
|
||||
toggleHost={toggleHost}
|
||||
toggleLoading={false}
|
||||
/>
|
||||
);
|
||||
expect(wrapper.find('PencilAltIcon').exists()).toBeFalsy();
|
||||
});
|
||||
|
||||
test('handles toggle click when host is enabled', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
<InventoryHostItem
|
||||
isSelected={false}
|
||||
detailUrl="/host/1"
|
||||
onSelect={() => {}}
|
||||
host={mockHost}
|
||||
toggleHost={toggleHost}
|
||||
toggleLoading={false}
|
||||
/>
|
||||
);
|
||||
wrapper
|
||||
.find('Switch')
|
||||
.first()
|
||||
.find('input')
|
||||
.simulate('change');
|
||||
expect(toggleHost).toHaveBeenCalledWith(mockHost);
|
||||
test('should display host toggle', () => {
|
||||
expect(wrapper.find('HostToggle').length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -28,8 +28,6 @@ function InventoryHostList({ i18n, location, match }) {
|
||||
const [hosts, setHosts] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [selected, setSelected] = useState([]);
|
||||
const [toggleError, setToggleError] = useState(null);
|
||||
const [toggleLoading, setToggleLoading] = useState(null);
|
||||
|
||||
const fetchHosts = (id, queryString) => {
|
||||
const params = parseQueryString(QS_CONFIG, queryString);
|
||||
@ -100,24 +98,6 @@ function InventoryHostList({ i18n, location, match }) {
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggle = async hostToToggle => {
|
||||
setToggleLoading(hostToToggle.id);
|
||||
|
||||
try {
|
||||
const { data: updatedHost } = await HostsAPI.update(hostToToggle.id, {
|
||||
enabled: !hostToToggle.enabled,
|
||||
});
|
||||
|
||||
setHosts(
|
||||
hosts.map(host => (host.id === updatedHost.id ? updatedHost : host))
|
||||
);
|
||||
} catch (error) {
|
||||
setToggleError(error);
|
||||
} finally {
|
||||
setToggleLoading(null);
|
||||
}
|
||||
};
|
||||
|
||||
const canAdd =
|
||||
actions && Object.prototype.hasOwnProperty.call(actions, 'POST');
|
||||
const isAllSelected = selected.length > 0 && selected.length === hosts.length;
|
||||
@ -184,8 +164,6 @@ function InventoryHostList({ i18n, location, match }) {
|
||||
editUrl={`/inventories/inventory/${match.params.id}/hosts/${o.id}/edit`}
|
||||
isSelected={selected.some(row => row.id === o.id)}
|
||||
onSelect={() => handleSelect(o)}
|
||||
toggleHost={handleToggle}
|
||||
toggleLoading={toggleLoading === o.id}
|
||||
/>
|
||||
)}
|
||||
emptyStateControls={
|
||||
@ -197,19 +175,6 @@ function InventoryHostList({ i18n, location, match }) {
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
{toggleError && !toggleLoading && (
|
||||
<AlertModal
|
||||
variant="error"
|
||||
title={i18n._(t`Error!`)}
|
||||
isOpen={toggleError && !toggleLoading}
|
||||
onClose={() => setToggleError(false)}
|
||||
>
|
||||
{i18n._(t`Failed to toggle host.`)}
|
||||
<ErrorDetail error={toggleError} />
|
||||
</AlertModal>
|
||||
)}
|
||||
|
||||
{deletionError && (
|
||||
<AlertModal
|
||||
isOpen={deletionError}
|
||||
|
||||
@ -60,7 +60,14 @@ const mockHosts = [
|
||||
delete: false,
|
||||
update: false,
|
||||
},
|
||||
recent_jobs: [],
|
||||
recent_jobs: [
|
||||
{
|
||||
id: 123,
|
||||
name: 'Recent Job',
|
||||
status: 'success',
|
||||
finished: '2020-01-27T19:40:36.208728Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user