foreman_remote_execution 3.3.4 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/app/controllers/api/v2/job_invocations_controller.rb +1 -0
- data/app/controllers/foreman_remote_execution/concerns/api/v2/subnets_controller_extensions.rb +21 -0
- data/app/controllers/job_invocations_controller.rb +22 -8
- data/app/helpers/job_invocations_helper.rb +3 -2
- data/app/lib/actions/remote_execution/run_host_job.rb +1 -1
- data/app/lib/actions/remote_execution/run_hosts_job.rb +4 -3
- data/app/lib/foreman_remote_execution/renderer/scope/input.rb +35 -0
- data/app/models/concerns/api/v2/interfaces_controller_extensions.rb +13 -0
- data/app/models/concerns/foreman_remote_execution/orchestration/ssh.rb +11 -4
- data/app/models/job_invocation.rb +11 -4
- data/app/models/job_invocation_composer.rb +2 -2
- data/app/models/remote_execution_provider.rb +2 -2
- data/app/models/setting/remote_execution.rb +2 -2
- data/app/models/ssh_execution_provider.rb +1 -1
- data/app/views/api/v2/interfaces/execution_flag.json.rabl +1 -0
- data/app/views/api/v2/job_invocations/base.json.rabl +1 -0
- data/app/views/api/v2/job_invocations/main.json.rabl +1 -1
- data/app/views/api/v2/subnets/remote_execution_proxies.json.rabl +3 -0
- data/app/views/job_invocations/_form.html.erb +1 -1
- data/app/views/job_invocations/_tab_hosts.html.erb +1 -20
- data/app/views/job_invocations/_tab_overview.html.erb +13 -1
- data/app/views/job_invocations/show.html.erb +9 -0
- data/app/views/job_invocations/show.js.erb +5 -0
- data/app/views/job_invocations/show.json.erb +2 -1
- data/db/migrate/20200623073022_rename_sudo_password_to_effective_user_password.rb +34 -0
- data/db/seeds.d/20-permissions.rb +9 -0
- data/lib/foreman_remote_execution/engine.rb +19 -1
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/test/functional/api/v2/job_invocations_controller_test.rb +65 -2
- data/test/functional/job_invocations_controller_test.rb +71 -0
- data/test/models/orchestration/ssh_test.rb +1 -1
- data/test/support/remote_execution_helper.rb +5 -0
- data/test/unit/actions/run_host_job_test.rb +3 -3
- data/test/unit/actions/run_hosts_job_test.rb +2 -2
- data/test/unit/job_invocation_composer_test.rb +5 -5
- data/test/unit/remote_execution_provider_test.rb +6 -6
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
- data/webpack/__mocks__/foremanReact/components/SearchBar.js +2 -0
- data/webpack/__mocks__/foremanReact/constants.js +21 -0
- data/webpack/__mocks__/foremanReact/redux/API/APISelectors.js +2 -0
- data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors.js +1 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHosts.js +21 -15
- data/webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js +10 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +62 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.scss +6 -0
- data/webpack/react_app/components/TargetingHosts/TargetingHostsSelectors.js +10 -2
- data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsPage.test.js +9 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/TargetingHostsSelectors.test.js +26 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap +16 -1
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +68 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsSelectors.test.js.snap +11 -0
- data/webpack/react_app/components/TargetingHosts/__tests__/fixtures.js +35 -19
- data/webpack/react_app/components/TargetingHosts/index.js +73 -13
- metadata +22 -3
- data/webpack/react_app/components/TargetingHosts/TargetingHostsActions.js +0 -8
@@ -0,0 +1 @@
|
|
1
|
+
export const selectDoesIntervalExist = () => false;
|
@@ -5,8 +5,8 @@ import { LoadingState, Alert } from 'patternfly-react';
|
|
5
5
|
import { STATUS } from 'foremanReact/constants';
|
6
6
|
import HostItem from './components/HostItem';
|
7
7
|
|
8
|
-
const TargetingHosts = ({
|
9
|
-
if (
|
8
|
+
const TargetingHosts = ({ apiStatus, items }) => {
|
9
|
+
if (apiStatus === STATUS.ERROR) {
|
10
10
|
return (
|
11
11
|
<Alert type="error">
|
12
12
|
{__(
|
@@ -16,8 +16,24 @@ const TargetingHosts = ({ status, items }) => {
|
|
16
16
|
);
|
17
17
|
}
|
18
18
|
|
19
|
+
const tableBodyRows = items.length ? (
|
20
|
+
items.map(({ name, link, status, actions }) => (
|
21
|
+
<HostItem
|
22
|
+
key={name}
|
23
|
+
name={name}
|
24
|
+
link={link}
|
25
|
+
status={status}
|
26
|
+
actions={actions}
|
27
|
+
/>
|
28
|
+
))
|
29
|
+
) : (
|
30
|
+
<tr>
|
31
|
+
<td colSpan="3">{__('No hosts found.')}</td>
|
32
|
+
</tr>
|
33
|
+
);
|
34
|
+
|
19
35
|
return (
|
20
|
-
<LoadingState loading={!items.length}>
|
36
|
+
<LoadingState loading={!items.length && apiStatus === STATUS.PENDING}>
|
21
37
|
<div>
|
22
38
|
<table className="table table-bordered table-striped table-hover">
|
23
39
|
<thead>
|
@@ -27,17 +43,7 @@ const TargetingHosts = ({ status, items }) => {
|
|
27
43
|
<th>{__('Actions')}</th>
|
28
44
|
</tr>
|
29
45
|
</thead>
|
30
|
-
<tbody>
|
31
|
-
{items.map(host => (
|
32
|
-
<HostItem
|
33
|
-
key={host.name}
|
34
|
-
name={host.name}
|
35
|
-
link={host.link}
|
36
|
-
status={host.status}
|
37
|
-
actions={host.actions}
|
38
|
-
/>
|
39
|
-
))}
|
40
|
-
</tbody>
|
46
|
+
<tbody>{tableBodyRows}</tbody>
|
41
47
|
</table>
|
42
48
|
</div>
|
43
49
|
</LoadingState>
|
@@ -45,7 +51,7 @@ const TargetingHosts = ({ status, items }) => {
|
|
45
51
|
};
|
46
52
|
|
47
53
|
TargetingHosts.propTypes = {
|
48
|
-
|
54
|
+
apiStatus: PropTypes.string.isRequired,
|
49
55
|
items: PropTypes.array.isRequired,
|
50
56
|
};
|
51
57
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { getURI } from 'foremanReact/common/urlHelpers';
|
2
|
+
|
3
|
+
export const getApiUrl = (searchQuery, pagination) => {
|
4
|
+
const baseUrl = getURI()
|
5
|
+
.search('')
|
6
|
+
.addQuery('page', pagination.page)
|
7
|
+
.addQuery('per_page', pagination.perPage);
|
8
|
+
|
9
|
+
return searchQuery ? baseUrl.addQuery('search', searchQuery) : baseUrl;
|
10
|
+
};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { Grid } from 'patternfly-react';
|
4
|
+
|
5
|
+
import SearchBar from 'foremanReact/components/SearchBar';
|
6
|
+
import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
|
7
|
+
import { getControllerSearchProps } from 'foremanReact/constants';
|
8
|
+
|
9
|
+
import TargetingHosts from './TargetingHosts';
|
10
|
+
import './TargetingHostsPage.scss';
|
11
|
+
|
12
|
+
const TargetingHostsPage = ({
|
13
|
+
handleSearch,
|
14
|
+
searchQuery,
|
15
|
+
apiStatus,
|
16
|
+
items,
|
17
|
+
totalHosts,
|
18
|
+
pagination,
|
19
|
+
handlePagination,
|
20
|
+
}) => (
|
21
|
+
<div id="targeting_hosts">
|
22
|
+
<Grid.Row>
|
23
|
+
<Grid.Col md={6} className="title_filter">
|
24
|
+
<SearchBar
|
25
|
+
onSearch={query => handleSearch(query)}
|
26
|
+
data={{
|
27
|
+
...getControllerSearchProps('hosts'),
|
28
|
+
autocomplete: {
|
29
|
+
id: 'targeting_hosts_search',
|
30
|
+
searchQuery,
|
31
|
+
url: '/hosts/auto_complete_search',
|
32
|
+
useKeyShortcuts: true,
|
33
|
+
},
|
34
|
+
bookmarks: {},
|
35
|
+
}}
|
36
|
+
/>
|
37
|
+
</Grid.Col>
|
38
|
+
</Grid.Row>
|
39
|
+
<br />
|
40
|
+
<TargetingHosts apiStatus={apiStatus} items={items} />
|
41
|
+
<Pagination
|
42
|
+
viewType="list"
|
43
|
+
itemCount={totalHosts}
|
44
|
+
pagination={pagination}
|
45
|
+
onChange={args => handlePagination(args)}
|
46
|
+
dropdownButtonId="targeting-hosts-pagination-dropdown"
|
47
|
+
className="targeting-hosts-pagination"
|
48
|
+
/>
|
49
|
+
</div>
|
50
|
+
);
|
51
|
+
|
52
|
+
TargetingHostsPage.propTypes = {
|
53
|
+
handleSearch: PropTypes.func.isRequired,
|
54
|
+
searchQuery: PropTypes.string.isRequired,
|
55
|
+
apiStatus: PropTypes.string.isRequired,
|
56
|
+
items: PropTypes.array.isRequired,
|
57
|
+
totalHosts: PropTypes.number.isRequired,
|
58
|
+
pagination: PropTypes.object.isRequired,
|
59
|
+
handlePagination: PropTypes.func.isRequired,
|
60
|
+
};
|
61
|
+
|
62
|
+
export default TargetingHostsPage;
|
@@ -2,11 +2,19 @@ import {
|
|
2
2
|
selectAPIStatus,
|
3
3
|
selectAPIResponse,
|
4
4
|
} from 'foremanReact/redux/API/APISelectors';
|
5
|
+
import { selectDoesIntervalExist } from 'foremanReact/redux/middlewares/IntervalMiddleware/IntervalSelectors';
|
6
|
+
|
5
7
|
import { TARGETING_HOSTS } from './TargetingHostsConsts';
|
6
8
|
|
7
9
|
export const selectItems = state =>
|
8
10
|
selectAPIResponse(state, TARGETING_HOSTS).hosts || [];
|
9
11
|
|
10
12
|
export const selectAutoRefresh = state =>
|
11
|
-
selectAPIResponse(state, TARGETING_HOSTS).autoRefresh;
|
12
|
-
|
13
|
+
selectAPIResponse(state, TARGETING_HOSTS).autoRefresh || '';
|
14
|
+
|
15
|
+
export const selectApiStatus = state => selectAPIStatus(state, TARGETING_HOSTS);
|
16
|
+
export const selectTotalHosts = state =>
|
17
|
+
selectAPIResponse(state, TARGETING_HOSTS).total_hosts || 0;
|
18
|
+
|
19
|
+
export const selectIntervalExists = state =>
|
20
|
+
selectDoesIntervalExist(state, TARGETING_HOSTS);
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
|
2
|
+
import TargetingHostsPage from '../TargetingHostsPage';
|
3
|
+
import { TargetingHostsPageFixtures } from './fixtures';
|
4
|
+
|
5
|
+
describe('TargetingHostsPage', () =>
|
6
|
+
testComponentSnapshotsWithFixtures(
|
7
|
+
TargetingHostsPage,
|
8
|
+
TargetingHostsPageFixtures
|
9
|
+
));
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { testSelectorsSnapshotWithFixtures } from '@theforeman/test';
|
2
|
+
|
3
|
+
import {
|
4
|
+
selectItems,
|
5
|
+
selectAutoRefresh,
|
6
|
+
selectApiStatus,
|
7
|
+
selectTotalHosts,
|
8
|
+
selectIntervalExists,
|
9
|
+
} from '../TargetingHostsSelectors';
|
10
|
+
|
11
|
+
const state = {
|
12
|
+
hosts: [],
|
13
|
+
autoRefresh: 'true',
|
14
|
+
total_hosts: 0,
|
15
|
+
};
|
16
|
+
|
17
|
+
const fixtures = {
|
18
|
+
'should return hosts': () => selectItems(state),
|
19
|
+
'should return autoRefresh': () => selectAutoRefresh(state),
|
20
|
+
'should return apiStatus': () => selectApiStatus(state),
|
21
|
+
'should return totalHosts': () => selectTotalHosts(state),
|
22
|
+
'should return intervalExists': () => selectIntervalExists(state),
|
23
|
+
};
|
24
|
+
|
25
|
+
describe('TargetingHostsSelectors', () =>
|
26
|
+
testSelectorsSnapshotWithFixtures(fixtures));
|
data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHosts.test.js.snap
CHANGED
@@ -33,6 +33,13 @@ exports[`TargetingHosts renders 1`] = `
|
|
33
33
|
name="host"
|
34
34
|
status="success"
|
35
35
|
/>
|
36
|
+
<HostItem
|
37
|
+
actions={Array []}
|
38
|
+
key="host2"
|
39
|
+
link="/link2"
|
40
|
+
name="host2"
|
41
|
+
status="success"
|
42
|
+
/>
|
36
43
|
</tbody>
|
37
44
|
</table>
|
38
45
|
</div>
|
@@ -74,7 +81,15 @@ exports[`TargetingHosts renders with loading 1`] = `
|
|
74
81
|
</th>
|
75
82
|
</tr>
|
76
83
|
</thead>
|
77
|
-
<tbody
|
84
|
+
<tbody>
|
85
|
+
<tr>
|
86
|
+
<td
|
87
|
+
colSpan="3"
|
88
|
+
>
|
89
|
+
No hosts found.
|
90
|
+
</td>
|
91
|
+
</tr>
|
92
|
+
</tbody>
|
78
93
|
</table>
|
79
94
|
</div>
|
80
95
|
</LoadingState>
|
@@ -0,0 +1,68 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`TargetingHostsPage renders 1`] = `
|
4
|
+
<div
|
5
|
+
id="targeting_hosts"
|
6
|
+
>
|
7
|
+
<Row
|
8
|
+
bsClass="row"
|
9
|
+
componentClass="div"
|
10
|
+
>
|
11
|
+
<Col
|
12
|
+
bsClass="col"
|
13
|
+
className="title_filter"
|
14
|
+
componentClass="div"
|
15
|
+
md={6}
|
16
|
+
>
|
17
|
+
<SearchBar
|
18
|
+
data={
|
19
|
+
Object {
|
20
|
+
"autocomplete": Object {
|
21
|
+
"id": "targeting_hosts_search",
|
22
|
+
"searchQuery": "",
|
23
|
+
"url": "/hosts/auto_complete_search",
|
24
|
+
"useKeyShortcuts": true,
|
25
|
+
},
|
26
|
+
"bookmarks": Object {},
|
27
|
+
"controller": "hosts",
|
28
|
+
}
|
29
|
+
}
|
30
|
+
onSearch={[Function]}
|
31
|
+
/>
|
32
|
+
</Col>
|
33
|
+
</Row>
|
34
|
+
<br />
|
35
|
+
<TargetingHosts
|
36
|
+
apiStatus="RESOLVED"
|
37
|
+
items={
|
38
|
+
Array [
|
39
|
+
Object {
|
40
|
+
"actions": Array [],
|
41
|
+
"link": "/link",
|
42
|
+
"name": "host",
|
43
|
+
"status": "success",
|
44
|
+
},
|
45
|
+
Object {
|
46
|
+
"actions": Array [],
|
47
|
+
"link": "/link2",
|
48
|
+
"name": "host2",
|
49
|
+
"status": "success",
|
50
|
+
},
|
51
|
+
]
|
52
|
+
}
|
53
|
+
/>
|
54
|
+
<PaginationWrapper
|
55
|
+
className="targeting-hosts-pagination"
|
56
|
+
dropdownButtonId="targeting-hosts-pagination-dropdown"
|
57
|
+
itemCount={1}
|
58
|
+
onChange={[Function]}
|
59
|
+
pagination={
|
60
|
+
Object {
|
61
|
+
"page": 1,
|
62
|
+
"perPage": 20,
|
63
|
+
}
|
64
|
+
}
|
65
|
+
viewType="list"
|
66
|
+
/>
|
67
|
+
</div>
|
68
|
+
`;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`TargetingHostsSelectors should return apiStatus 1`] = `"RESOLVED"`;
|
4
|
+
|
5
|
+
exports[`TargetingHostsSelectors should return autoRefresh 1`] = `"true"`;
|
6
|
+
|
7
|
+
exports[`TargetingHostsSelectors should return hosts 1`] = `Array []`;
|
8
|
+
|
9
|
+
exports[`TargetingHostsSelectors should return intervalExists 1`] = `false`;
|
10
|
+
|
11
|
+
exports[`TargetingHostsSelectors should return totalHosts 1`] = `0`;
|
@@ -1,3 +1,18 @@
|
|
1
|
+
const items = [
|
2
|
+
{
|
3
|
+
name: 'host',
|
4
|
+
link: '/link',
|
5
|
+
status: 'success',
|
6
|
+
actions: [],
|
7
|
+
},
|
8
|
+
{
|
9
|
+
name: 'host2',
|
10
|
+
link: '/link2',
|
11
|
+
status: 'success',
|
12
|
+
actions: [],
|
13
|
+
},
|
14
|
+
];
|
15
|
+
|
1
16
|
export const HostItemFixtures = {
|
2
17
|
renders: {
|
3
18
|
name: 'Host1',
|
@@ -15,29 +30,30 @@ export const HostStatusFixtures = {
|
|
15
30
|
|
16
31
|
export const TargetingHostsFixtures = {
|
17
32
|
renders: {
|
18
|
-
|
19
|
-
items
|
20
|
-
{
|
21
|
-
name: 'host',
|
22
|
-
link: '/link',
|
23
|
-
status: 'success',
|
24
|
-
actions: [],
|
25
|
-
},
|
26
|
-
],
|
33
|
+
apiStatus: 'RESOLVED',
|
34
|
+
items,
|
27
35
|
},
|
28
36
|
'renders with error': {
|
29
|
-
|
30
|
-
items
|
31
|
-
{
|
32
|
-
name: 'host',
|
33
|
-
link: '/link',
|
34
|
-
status: 'success',
|
35
|
-
actions: [],
|
36
|
-
},
|
37
|
-
],
|
37
|
+
apiStatus: 'ERROR',
|
38
|
+
items,
|
38
39
|
},
|
39
40
|
'renders with loading': {
|
40
|
-
|
41
|
+
apiStatus: 'PENDING',
|
41
42
|
items: [],
|
42
43
|
},
|
43
44
|
};
|
45
|
+
|
46
|
+
export const TargetingHostsPageFixtures = {
|
47
|
+
renders: {
|
48
|
+
handleSearch: () => {},
|
49
|
+
searchQuery: '',
|
50
|
+
apiStatus: 'RESOLVED',
|
51
|
+
items,
|
52
|
+
totalHosts: 1,
|
53
|
+
pagination: {
|
54
|
+
page: 1,
|
55
|
+
perPage: 20,
|
56
|
+
},
|
57
|
+
handlePagination: () => {},
|
58
|
+
},
|
59
|
+
};
|
@@ -1,37 +1,97 @@
|
|
1
|
-
import React, { useEffect } from 'react';
|
1
|
+
import React, { useEffect, useState } from 'react';
|
2
2
|
import { useSelector, useDispatch } from 'react-redux';
|
3
|
-
|
4
|
-
import
|
3
|
+
|
4
|
+
import { get } from 'foremanReact/redux/API';
|
5
|
+
import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
|
6
|
+
import {
|
7
|
+
withInterval,
|
8
|
+
stopInterval,
|
9
|
+
} from 'foremanReact/redux/middlewares/IntervalMiddleware';
|
5
10
|
|
6
11
|
import {
|
7
12
|
selectItems,
|
8
|
-
|
13
|
+
selectApiStatus,
|
9
14
|
selectAutoRefresh,
|
15
|
+
selectTotalHosts,
|
16
|
+
selectIntervalExists,
|
10
17
|
} from './TargetingHostsSelectors';
|
11
|
-
import {
|
18
|
+
import { getApiUrl } from './TargetingHostsHelpers';
|
12
19
|
import { TARGETING_HOSTS } from './TargetingHostsConsts';
|
20
|
+
import TargetingHostsPage from './TargetingHostsPage';
|
13
21
|
|
14
22
|
const WrappedTargetingHosts = () => {
|
15
23
|
const dispatch = useDispatch();
|
24
|
+
const { perPage, perPageOptions } = useForemanSettings();
|
25
|
+
|
16
26
|
const autoRefresh = useSelector(selectAutoRefresh);
|
17
27
|
const items = useSelector(selectItems);
|
18
|
-
const
|
28
|
+
const apiStatus = useSelector(selectApiStatus);
|
29
|
+
const totalHosts = useSelector(selectTotalHosts);
|
30
|
+
const [searchQuery, setSearchQuery] = useState('');
|
31
|
+
const [pagination, setPagination] = useState({
|
32
|
+
page: 1,
|
33
|
+
perPage,
|
34
|
+
perPageOptions,
|
35
|
+
});
|
36
|
+
const [apiUrl, setApiUrl] = useState(getApiUrl(searchQuery, pagination));
|
37
|
+
const intervalExists = useSelector(selectIntervalExists);
|
19
38
|
|
20
|
-
|
21
|
-
|
39
|
+
const handleSearch = query => {
|
40
|
+
const defaultPagination = { page: 1, perPage: pagination.perPage };
|
41
|
+
stopApiInterval();
|
22
42
|
|
23
|
-
|
43
|
+
setApiUrl(getApiUrl(query, defaultPagination));
|
44
|
+
setSearchQuery(query);
|
45
|
+
setPagination(defaultPagination);
|
46
|
+
};
|
47
|
+
|
48
|
+
const handlePagination = args => {
|
49
|
+
stopApiInterval();
|
50
|
+
setPagination(args);
|
51
|
+
setApiUrl(getApiUrl(searchQuery, args));
|
52
|
+
};
|
53
|
+
|
54
|
+
const stopApiInterval = () => {
|
55
|
+
if (intervalExists) {
|
24
56
|
dispatch(stopInterval(TARGETING_HOSTS));
|
25
|
-
}
|
26
|
-
}
|
57
|
+
}
|
58
|
+
};
|
59
|
+
|
60
|
+
const getData = url =>
|
61
|
+
withInterval(
|
62
|
+
get({
|
63
|
+
key: TARGETING_HOSTS,
|
64
|
+
url,
|
65
|
+
handleError: () => {
|
66
|
+
dispatch(stopInterval(TARGETING_HOSTS));
|
67
|
+
},
|
68
|
+
}),
|
69
|
+
1000
|
70
|
+
);
|
27
71
|
|
28
72
|
useEffect(() => {
|
73
|
+
dispatch(getData(apiUrl));
|
74
|
+
|
29
75
|
if (autoRefresh === 'false') {
|
30
76
|
dispatch(stopInterval(TARGETING_HOSTS));
|
31
77
|
}
|
32
|
-
}, [autoRefresh, dispatch]);
|
33
78
|
|
34
|
-
|
79
|
+
return () => {
|
80
|
+
dispatch(stopInterval(TARGETING_HOSTS));
|
81
|
+
};
|
82
|
+
}, [dispatch, apiUrl, autoRefresh]);
|
83
|
+
|
84
|
+
return (
|
85
|
+
<TargetingHostsPage
|
86
|
+
handleSearch={handleSearch}
|
87
|
+
searchQuery={searchQuery}
|
88
|
+
apiStatus={apiStatus}
|
89
|
+
items={items}
|
90
|
+
totalHosts={totalHosts}
|
91
|
+
pagination={pagination}
|
92
|
+
handlePagination={handlePagination}
|
93
|
+
/>
|
94
|
+
);
|
35
95
|
};
|
36
96
|
|
37
97
|
export default WrappedTargetingHosts;
|