foreman_rh_cloud 3.0.18.1 → 4.0.21.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -5
- data/app/controllers/foreman_inventory_upload/tasks_controller.rb +14 -3
- data/app/controllers/foreman_inventory_upload/uploads_settings_controller.rb +8 -0
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +17 -7
- data/app/controllers/insights_cloud/hits_controller.rb +37 -0
- data/app/controllers/insights_cloud/settings_controller.rb +1 -1
- data/app/controllers/insights_cloud/tasks_controller.rb +1 -2
- data/app/models/insights_client_report_status.rb +58 -0
- data/app/models/insights_resolution.rb +1 -1
- data/app/models/inventory_sync/inventory_status.rb +6 -0
- data/app/models/setting/rh_cloud.rb +5 -5
- data/app/services/foreman_rh_cloud/cloud_connector.rb +1 -1
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +78 -0
- data/app/services/foreman_rh_cloud/template_renderer_helper.rb +22 -0
- data/app/subscribers/foreman_rh_cloud/insights_subscriber.rb +9 -0
- data/app/views/job_templates/rh_cloud_remediations.erb +14 -0
- data/config/routes.rb +2 -1
- data/db/migrate/20210404000001_change_resolutions.foreman_rh_cloud.rb +10 -0
- data/db/seeds.d/179_ui_notifications.rb +11 -0
- data/db/seeds.d/50_job_templates.rb +14 -0
- data/lib/foreman_inventory_upload.rb +9 -0
- data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +8 -2
- data/lib/foreman_inventory_upload/generators/queries.rb +3 -2
- data/lib/foreman_inventory_upload/generators/slice.rb +1 -1
- data/lib/foreman_inventory_upload/generators/tags.rb +8 -6
- data/lib/foreman_inventory_upload/scripts/uploader.sh.erb +5 -1
- data/lib/foreman_rh_cloud.rb +18 -0
- data/lib/foreman_rh_cloud/engine.rb +36 -2
- data/lib/foreman_rh_cloud/version.rb +1 -1
- data/lib/insights_cloud.rb +12 -0
- data/lib/insights_cloud/async/insights_full_sync.rb +39 -24
- data/lib/insights_cloud/async/insights_generate_notifications.rb +58 -0
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +69 -0
- data/lib/insights_cloud/async/insights_rules_sync.rb +13 -17
- data/lib/insights_cloud/async/insights_scheduled_sync.rb +1 -1
- data/lib/inventory_sync/async/host_result.rb +11 -6
- data/lib/inventory_sync/async/inventory_full_sync.rb +24 -41
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +34 -0
- data/lib/inventory_sync/async/inventory_scheduled_sync.rb +17 -0
- data/lib/inventory_sync/async/query_inventory_job.rb +54 -0
- data/lib/tasks/insights.rake +4 -12
- data/lib/tasks/rh_cloud_inventory.rake +12 -4
- data/package.json +1 -1
- data/test/factories/insights_factories.rb +22 -0
- data/test/jobs/insights_full_sync_test.rb +28 -15
- data/test/jobs/insights_resolutions_sync_test.rb +77 -0
- data/test/jobs/insights_rules_sync_test.rb +8 -3
- data/test/jobs/inventory_full_sync_test.rb +185 -12
- data/test/models/insights_client_report_status_test.rb +77 -0
- data/test/unit/rh_cloud_http_proxy_test.rb +4 -4
- data/test/unit/services/foreman_rh_cloud/remediations_retriever_test.rb +49 -0
- data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +28 -0
- data/test/unit/slice_generator_test.rb +11 -2
- data/test/unit/tags_generator_test.rb +10 -0
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModal.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/__tests__/__snapshots__/FullScreenModal.test.js.snap +1 -1
- data/webpack/ForemanInventoryUpload/Components/FullScreenModal/fullScreenModal.scss +14 -16
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/integration.test.js.snap +0 -1
- data/webpack/ForemanInventoryUpload/Components/InventorySettings/AdvancedSetting/AdvancedSettingsConstants.js +5 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +15 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +13 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonActions.js +81 -46
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonConstants.js +3 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonSelectors.js +6 -12
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonFixtures.js +1 -9
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonSelectors.test.js +18 -27
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonSelectors.test.js.snap +1 -16
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/integrations.test.js.snap +58 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/integrations.test.js +51 -0
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/index.js +2 -5
- data/webpack/ForemanInventoryUpload/Components/Terminal/Terminal.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/Terminal/__tests__/Terminal.test.js +1 -1
- data/webpack/ForemanInventoryUpload/Components/Terminal/__tests__/__snapshots__/Terminal.test.js.snap +2 -2
- data/webpack/ForemanInventoryUpload/Components/Terminal/terminal.scss +25 -27
- data/webpack/ForemanInventoryUpload/ForemanInventoryUploadReducers.js +0 -2
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +3 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +2 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +59 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationActions.js +12 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationHelpers.js +43 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +101 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +9 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModalFooter.js +43 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationTableConstants.js +38 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/Resolutions.js +55 -0
- data/webpack/InsightsCloudSync/Components/RemediationModal/index.js +34 -0
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +8 -3
- data/webpack/InsightsCloudSync/InsightsCloudSync.scss +5 -0
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +9 -6
- data/webpack/__mocks__/foremanReact/redux/middlewares/IntervalMiddleware.js +4 -0
- data/webpack/{InsightsCloudSync/Components/InsightsTable/components → common/table}/EmptyState.js +0 -0
- data/webpack/common/table/helpers.js +7 -0
- metadata +56 -26
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonReducer.js +0 -36
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonActions.test.js +0 -31
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/SyncButtonReducer.test.js +0 -26
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonActions.test.js.snap +0 -98
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/SyncButtonReducer.test.js.snap +0 -18
@@ -1,3 +1,3 @@
|
|
1
|
-
export const
|
2
|
-
|
3
|
-
export const
|
1
|
+
export const INVENTORY_SYNC = 'INVENTORY_SYNC';
|
2
|
+
|
3
|
+
export const INVENTORY_SYNC_TASK_UPDATE = 'INVENTORY_SYNC_TASK_UPDATE';
|
@@ -1,13 +1,7 @@
|
|
1
|
-
import {
|
1
|
+
import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
|
2
|
+
import { INVENTORY_SYNC_TASK_UPDATE } from './SyncButtonConstants';
|
2
3
|
|
3
|
-
export const
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
export const selectError = state => selectInventorySync(state).error;
|
9
|
-
|
10
|
-
export const selectSyncHosts = state => selectInventorySync(state).syncHosts;
|
11
|
-
|
12
|
-
export const selectDisconnectHosts = state =>
|
13
|
-
selectInventorySync(state).disconnectHosts;
|
4
|
+
export const selectTaskStatus = state => {
|
5
|
+
const { result } = selectAPIResponse(state, INVENTORY_SYNC_TASK_UPDATE);
|
6
|
+
return typeof result === 'string' ? result.toUpperCase() : null;
|
7
|
+
};
|
@@ -1,9 +1 @@
|
|
1
|
-
export const
|
2
|
-
|
3
|
-
export const disconnectHosts = 0;
|
4
|
-
|
5
|
-
export const successResponse = { data: { syncHosts, disconnectHosts } };
|
6
|
-
|
7
|
-
export const status = 'RESOLVED';
|
8
|
-
|
9
|
-
export const error = 'some-error';
|
1
|
+
export const successResponse = { data: { task: { id: 1 } } };
|
@@ -1,35 +1,26 @@
|
|
1
1
|
import { testSelectorsSnapshotWithFixtures } from '@theforeman/test';
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
status,
|
5
|
-
error,
|
6
|
-
syncHosts,
|
7
|
-
disconnectHosts,
|
8
|
-
} from './SyncButtonFixtures';
|
9
|
-
import {
|
10
|
-
selectInventorySync,
|
11
|
-
selectStatus,
|
12
|
-
selectError,
|
13
|
-
selectSyncHosts,
|
14
|
-
selectDisconnectHosts,
|
15
|
-
} from '../SyncButtonSelectors';
|
2
|
+
import { selectTaskStatus } from '../SyncButtonSelectors';
|
16
3
|
|
17
|
-
const state =
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
4
|
+
const state = {
|
5
|
+
API: {
|
6
|
+
INVENTORY_SYNC_TASK_UPDATE: {
|
7
|
+
response: {
|
8
|
+
endedAt: '2021-03-08T14:27:30.718+02:00',
|
9
|
+
output: {
|
10
|
+
host_statuses: {
|
11
|
+
sync: 0,
|
12
|
+
disconnect: 2,
|
13
|
+
},
|
14
|
+
},
|
15
|
+
result: 'pending',
|
16
|
+
},
|
17
|
+
status: 'RESOLVED',
|
18
|
+
},
|
23
19
|
},
|
24
|
-
}
|
20
|
+
};
|
25
21
|
|
26
22
|
const fixtures = {
|
27
|
-
'should return InventorySync': () =>
|
28
|
-
'should return InventorySync status': () => selectStatus(state),
|
29
|
-
'should return InventorySync error': () => selectError(state),
|
30
|
-
'should return InventorySync SyncHosts': () => selectSyncHosts(state),
|
31
|
-
'should return InventorySync disconnectHosts': () =>
|
32
|
-
selectDisconnectHosts(state),
|
23
|
+
'should return InventorySync status': () => selectTaskStatus(state),
|
33
24
|
};
|
34
25
|
|
35
26
|
describe('SyncButton selectors', () =>
|
@@ -1,18 +1,3 @@
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
2
|
|
3
|
-
exports[`SyncButton selectors should return InventorySync 1`] = `
|
4
|
-
Object {
|
5
|
-
"disconnectHosts": 0,
|
6
|
-
"error": "some-error",
|
7
|
-
"status": "RESOLVED",
|
8
|
-
"syncHosts": 1,
|
9
|
-
}
|
10
|
-
`;
|
11
|
-
|
12
|
-
exports[`SyncButton selectors should return InventorySync SyncHosts 1`] = `1`;
|
13
|
-
|
14
|
-
exports[`SyncButton selectors should return InventorySync disconnectHosts 1`] = `0`;
|
15
|
-
|
16
|
-
exports[`SyncButton selectors should return InventorySync error 1`] = `"some-error"`;
|
17
|
-
|
18
|
-
exports[`SyncButton selectors should return InventorySync status 1`] = `"RESOLVED"`;
|
3
|
+
exports[`SyncButton selectors should return InventorySync status 1`] = `"PENDING"`;
|
@@ -0,0 +1,58 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`SyncButton integration test Successful task was triggered on the server resulting in an info toast and polling on the task: handleSync was called 1`] = `
|
4
|
+
Array [
|
5
|
+
Array [
|
6
|
+
Object {
|
7
|
+
"payload": Object {
|
8
|
+
"message": Object {
|
9
|
+
"message": <Toast
|
10
|
+
disconnectHosts={2}
|
11
|
+
syncHosts={0}
|
12
|
+
/>,
|
13
|
+
"sticky": true,
|
14
|
+
"type": "success",
|
15
|
+
},
|
16
|
+
},
|
17
|
+
"type": "TOASTS_ADD",
|
18
|
+
},
|
19
|
+
],
|
20
|
+
Array [
|
21
|
+
Object {
|
22
|
+
"errorToast": [Function],
|
23
|
+
"interval": 3000,
|
24
|
+
"type": "API_GET",
|
25
|
+
"url": "/foreman_inventory_upload/tasks/1",
|
26
|
+
},
|
27
|
+
],
|
28
|
+
Array [
|
29
|
+
Object {
|
30
|
+
"payload": Object {
|
31
|
+
"message": Object {
|
32
|
+
"message": <span>
|
33
|
+
Inventory sync has started:
|
34
|
+
|
35
|
+
<a
|
36
|
+
href="/foreman_tasks/tasks/1"
|
37
|
+
rel="noopener noreferrer"
|
38
|
+
target="_blank"
|
39
|
+
>
|
40
|
+
view the task page for more details
|
41
|
+
</a>
|
42
|
+
</span>,
|
43
|
+
"sticky": false,
|
44
|
+
"type": "info",
|
45
|
+
},
|
46
|
+
},
|
47
|
+
"type": "TOASTS_ADD",
|
48
|
+
},
|
49
|
+
],
|
50
|
+
Array [
|
51
|
+
Object {
|
52
|
+
"errorToast": [Function],
|
53
|
+
"type": "API_POST",
|
54
|
+
"url": "/foreman_inventory_upload/tasks",
|
55
|
+
},
|
56
|
+
],
|
57
|
+
]
|
58
|
+
`;
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { IntegrationTestHelper } from '@theforeman/test';
|
3
|
+
import * as API from 'foremanReact/redux/API';
|
4
|
+
import { noop } from 'foremanReact/common/helpers';
|
5
|
+
import SyncButton from '../index';
|
6
|
+
import { successResponse } from './SyncButtonFixtures';
|
7
|
+
import {
|
8
|
+
INVENTORY_SYNC,
|
9
|
+
INVENTORY_SYNC_TASK_UPDATE,
|
10
|
+
} from '../SyncButtonConstants';
|
11
|
+
|
12
|
+
jest.spyOn(API, 'post');
|
13
|
+
jest.spyOn(API, 'get');
|
14
|
+
|
15
|
+
describe('SyncButton integration test', () => {
|
16
|
+
it('Successful task was triggered on the server resulting in an info toast and polling on the task', async () => {
|
17
|
+
API.post.mockImplementation(({ handleSuccess = noop, key, ...action }) => {
|
18
|
+
if (key === INVENTORY_SYNC) {
|
19
|
+
handleSuccess(successResponse);
|
20
|
+
}
|
21
|
+
return { type: 'API_POST', ...action };
|
22
|
+
});
|
23
|
+
API.get.mockImplementation(({ handleSuccess = noop, key, ...action }) => {
|
24
|
+
if (key === INVENTORY_SYNC_TASK_UPDATE) {
|
25
|
+
handleSuccess(
|
26
|
+
{
|
27
|
+
data: {
|
28
|
+
endedAt: '2021-03-22T15:59:02.468+02:00',
|
29
|
+
output: {
|
30
|
+
host_statuses: {
|
31
|
+
sync: 0,
|
32
|
+
disconnect: 2,
|
33
|
+
},
|
34
|
+
},
|
35
|
+
result: 'success',
|
36
|
+
},
|
37
|
+
},
|
38
|
+
jest.fn
|
39
|
+
);
|
40
|
+
}
|
41
|
+
return { type: 'API_GET', ...action };
|
42
|
+
});
|
43
|
+
|
44
|
+
const integrationTestHelper = new IntegrationTestHelper();
|
45
|
+
const wrapper = integrationTestHelper.mount(<SyncButton />);
|
46
|
+
const instance = wrapper.find('SyncButton').instance();
|
47
|
+
instance.props.handleSync();
|
48
|
+
await IntegrationTestHelper.flushAllPromises();
|
49
|
+
integrationTestHelper.takeActionsSnapshot('handleSync was called');
|
50
|
+
});
|
51
|
+
});
|
@@ -2,21 +2,18 @@ import { bindActionCreators } from 'redux';
|
|
2
2
|
import { connect } from 'react-redux';
|
3
3
|
|
4
4
|
import * as actions from './SyncButtonActions';
|
5
|
-
import reducer from './SyncButtonReducer';
|
6
5
|
import SyncButton from './SyncButton';
|
7
6
|
import { selectCloudToken } from '../../../InventorySettings/InventorySettingsSelectors';
|
8
|
-
import {
|
7
|
+
import { selectTaskStatus } from './SyncButtonSelectors';
|
9
8
|
|
10
9
|
// map state to props
|
11
10
|
const mapStateToProps = state => ({
|
12
11
|
cloudToken: selectCloudToken(state),
|
13
|
-
status:
|
12
|
+
status: selectTaskStatus(state),
|
14
13
|
});
|
15
14
|
|
16
15
|
// map action dispatchers to props
|
17
16
|
const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
|
18
17
|
|
19
|
-
export const reducers = { inventorySync: reducer };
|
20
|
-
|
21
18
|
// export connected component
|
22
19
|
export default connect(mapStateToProps, mapDispatchToProps)(SyncButton);
|
@@ -29,6 +29,6 @@ describe('Terminal', () => {
|
|
29
29
|
const text = 'some-string-log';
|
30
30
|
const modifiedProps = { ...props, logs: text };
|
31
31
|
const wrapper = mount(<Terminal {...modifiedProps} />);
|
32
|
-
expect(wrapper.find('.terminal p').text()).toEqual(text);
|
32
|
+
expect(wrapper.find('.rh-cloud-inventory-terminal p').text()).toEqual(text);
|
33
33
|
});
|
34
34
|
});
|
@@ -7,7 +7,7 @@ exports[`Terminal rendering render with props 1`] = `
|
|
7
7
|
sm={12}
|
8
8
|
>
|
9
9
|
<div
|
10
|
-
className="terminal"
|
10
|
+
className="rh-cloud-inventory-terminal"
|
11
11
|
onScroll={[Function]}
|
12
12
|
>
|
13
13
|
<Grid
|
@@ -65,7 +65,7 @@ exports[`Terminal rendering render without Props 1`] = `
|
|
65
65
|
sm={12}
|
66
66
|
>
|
67
67
|
<div
|
68
|
-
className="terminal"
|
68
|
+
className="rh-cloud-inventory-terminal"
|
69
69
|
onScroll={[Function]}
|
70
70
|
>
|
71
71
|
<Grid
|
@@ -1,34 +1,32 @@
|
|
1
|
-
.rh-cloud-inventory-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
overflow-x: hidden;
|
1
|
+
.rh-cloud-inventory-terminal {
|
2
|
+
height: 200px;
|
3
|
+
background-color: #222;
|
4
|
+
padding: 10px 0;
|
5
|
+
margin-bottom: 20px;
|
6
|
+
overflow-y: scroll;
|
7
|
+
overflow-x: hidden;
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
p {
|
10
|
+
font-family: monospace;
|
11
|
+
font-size: 16px;
|
12
|
+
color: #22da26;
|
13
|
+
overflow-wrap: anywhere;
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
}
|
15
|
+
&.terminal_error {
|
16
|
+
color: #f00;
|
19
17
|
}
|
18
|
+
}
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
&::-webkit-scrollbar {
|
21
|
+
width: 12px;
|
22
|
+
height: 12px;
|
23
|
+
background: #aaa;
|
24
|
+
}
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
}
|
26
|
+
&::-webkit-scrollbar-thumb {
|
27
|
+
background: #222;
|
28
|
+
border-radius: 6px;
|
29
|
+
border: 3px solid transparent;
|
30
|
+
background-clip: content-box;
|
33
31
|
}
|
34
32
|
}
|
@@ -2,13 +2,11 @@ import { combineReducers } from 'redux';
|
|
2
2
|
import { reducers as accountListReducers } from './Components/AccountList';
|
3
3
|
import { reducers as dashboardReducers } from './Components/Dashboard';
|
4
4
|
import { reducers as filterReducers } from './Components/InventoryFilter';
|
5
|
-
import { reducers as inventorySyncReducers } from './Components/PageHeader/components/SyncButton';
|
6
5
|
|
7
6
|
export default {
|
8
7
|
inventoryUpload: combineReducers({
|
9
8
|
...accountListReducers,
|
10
9
|
...dashboardReducers,
|
11
10
|
...filterReducers,
|
12
|
-
...inventorySyncReducers,
|
13
11
|
}),
|
14
12
|
};
|
@@ -6,7 +6,7 @@ import { Table, TableHeader, TableBody } from '@patternfly/react-table';
|
|
6
6
|
import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
|
7
7
|
import SelectAllAlert from './SelectAllAlert';
|
8
8
|
import { columns } from './InsightsTableConstants';
|
9
|
-
import TableEmptyState from '
|
9
|
+
import TableEmptyState from '../../../common/table/EmptyState';
|
10
10
|
import {
|
11
11
|
modifySelectedRows,
|
12
12
|
getSortColumnIndex,
|
@@ -61,6 +61,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
|
|
61
61
|
expandId="expandable-toggle"
|
62
62
|
gridBreakPoint="grid-md"
|
63
63
|
isStickyHeader={false}
|
64
|
+
isTreeTable={false}
|
64
65
|
onSelect={[Function]}
|
65
66
|
onSort={[Function]}
|
66
67
|
ouiaSafe={true}
|
@@ -137,6 +138,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
|
|
137
138
|
"currPage": "Current page",
|
138
139
|
"items": "",
|
139
140
|
"itemsPerPage": "Items per page",
|
141
|
+
"ofWord": "of",
|
140
142
|
"optionsToggle": "Items per page",
|
141
143
|
"page": "",
|
142
144
|
"paginationTitle": "Pagination",
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { isEmpty } from 'lodash';
|
4
|
+
import { Button, Popover } from '@patternfly/react-core';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
import { foremanUrl } from '../../../ForemanRhCloudHelpers';
|
7
|
+
|
8
|
+
const RemediateButton = ({ isExperimentalMode, selectedIds, toggleModal }) => {
|
9
|
+
const [isVisible, setVisible] = React.useState(true);
|
10
|
+
|
11
|
+
const popoverContent = __(
|
12
|
+
`To use this feature, please enable <a href=${foremanUrl(
|
13
|
+
'/settings?search=name+%3D+lab_features'
|
14
|
+
)}>Show Experimental Labs</a> in settings.`
|
15
|
+
);
|
16
|
+
|
17
|
+
let button = (
|
18
|
+
<Button
|
19
|
+
variant="primary"
|
20
|
+
isDisabled={isEmpty(selectedIds)}
|
21
|
+
onClick={() => {
|
22
|
+
if (!isExperimentalMode) {
|
23
|
+
setVisible(value => !value);
|
24
|
+
} else {
|
25
|
+
toggleModal();
|
26
|
+
}
|
27
|
+
}}
|
28
|
+
>
|
29
|
+
{__('Remediate')}
|
30
|
+
</Button>
|
31
|
+
);
|
32
|
+
|
33
|
+
if (!isExperimentalMode) {
|
34
|
+
button = (
|
35
|
+
<Popover
|
36
|
+
isVisible={isVisible}
|
37
|
+
bodyContent={
|
38
|
+
<div dangerouslySetInnerHTML={{ __html: popoverContent }} />
|
39
|
+
}
|
40
|
+
>
|
41
|
+
{button}
|
42
|
+
</Popover>
|
43
|
+
);
|
44
|
+
}
|
45
|
+
return button;
|
46
|
+
};
|
47
|
+
|
48
|
+
RemediateButton.propTypes = {
|
49
|
+
selectedIds: PropTypes.object,
|
50
|
+
isExperimentalMode: PropTypes.bool,
|
51
|
+
toggleModal: PropTypes.func.isRequired,
|
52
|
+
};
|
53
|
+
|
54
|
+
RemediateButton.defaultProps = {
|
55
|
+
selectedIds: {},
|
56
|
+
isExperimentalMode: false,
|
57
|
+
};
|
58
|
+
|
59
|
+
export default RemediateButton;
|