foreman_rh_cloud 3.0.19 → 3.0.23
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/api/v2/rh_cloud/inventory_controller.rb +50 -0
- data/app/controllers/concerns/inventory_upload/report_actions.rb +26 -0
- data/app/controllers/concerns/inventory_upload/task_actions.rb +25 -0
- data/app/controllers/foreman_inventory_upload/reports_controller.rb +3 -1
- data/app/controllers/foreman_inventory_upload/tasks_controller.rb +5 -13
- data/app/controllers/foreman_inventory_upload/uploads_controller.rb +4 -4
- data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +18 -7
- data/app/controllers/insights_cloud/hits_controller.rb +42 -1
- data/app/controllers/insights_cloud/settings_controller.rb +1 -1
- data/app/controllers/insights_cloud/tasks_controller.rb +1 -2
- data/app/helpers/foreman_insights_host_helper.rb +19 -0
- data/app/models/insights_client_report_status.rb +58 -0
- 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_auth.rb +12 -0
- data/app/services/foreman_rh_cloud/cloud_connector.rb +1 -1
- data/app/services/foreman_rh_cloud/cloud_request.rb +14 -0
- data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +1 -6
- data/app/services/foreman_rh_cloud/remediations_retriever.rb +75 -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/package-lock.json.plugin +32774 -0
- data/config/routes.rb +20 -0
- 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 +5 -1
- data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +8 -2
- data/lib/foreman_inventory_upload/generators/fact_helpers.rb +19 -0
- data/lib/foreman_inventory_upload/generators/queries.rb +3 -2
- data/lib/foreman_inventory_upload/generators/slice.rb +6 -6
- data/lib/foreman_inventory_upload/generators/tags.rb +8 -6
- data/lib/foreman_rh_cloud.rb +18 -0
- data/lib/foreman_rh_cloud/engine.rb +40 -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 +31 -22
- data/lib/insights_cloud/async/insights_generate_notifications.rb +58 -0
- data/lib/insights_cloud/async/insights_resolutions_sync.rb +66 -0
- data/lib/insights_cloud/async/insights_rules_sync.rb +15 -24
- data/lib/insights_cloud/async/insights_scheduled_sync.rb +1 -1
- data/lib/inventory_sync/async/inventory_full_sync.rb +2 -1
- data/lib/inventory_sync/async/inventory_hosts_sync.rb +6 -2
- data/lib/inventory_sync/async/inventory_scheduled_sync.rb +29 -0
- data/lib/inventory_sync/async/query_inventory_job.rb +1 -4
- data/lib/tasks/insights.rake +4 -12
- data/lib/tasks/rh_cloud_inventory.rake +20 -5
- data/package.json +1 -1
- data/test/controllers/inventory_upload/api/inventory_controller_test.rb +53 -0
- data/test/factories/insights_factories.rb +22 -0
- data/test/factories/inventory_upload_factories.rb +1 -1
- data/test/jobs/insights_full_sync_test.rb +17 -8
- 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 +4 -1
- data/test/jobs/inventory_hosts_sync_test.rb +265 -0
- data/test/jobs/inventory_scheduled_sync_test.rb +22 -0
- data/test/models/insights_client_report_status_test.rb +77 -0
- data/test/test_plugin_helper.rb +2 -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 +66 -29
- 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/InventorySettings/AdvancedSetting/AdvancedSettingsConstants.js +5 -3
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +26 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +24 -2
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/SyncButtonActions.js +28 -63
- data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/__tests__/__snapshots__/integrations.test.js.snap +2 -3
- 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/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +1 -1
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableActions.js +19 -19
- data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +3 -0
- data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableActions.test.js.snap +14 -14
- data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +60 -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/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap +20 -13
- data/webpack/InsightsCloudSync/InsightsCloudSync.js +11 -3
- data/webpack/InsightsCloudSync/InsightsCloudSync.scss +5 -0
- data/webpack/InsightsCloudSync/InsightsCloudSyncActions.js +44 -20
- data/webpack/InsightsCloudSync/InsightsCloudSyncConstants.js +2 -0
- data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +9 -6
- data/webpack/InsightsCloudSync/__tests__/__snapshots__/InsightsCloudSyncActions.test.js.snap +11 -7
- data/webpack/common/ForemanTasks/ForemanTasksActions.js +64 -0
- data/webpack/common/ForemanTasks/ForemanTasksHelpers.js +7 -0
- data/webpack/common/ForemanTasks/index.js +1 -0
- data/webpack/{InsightsCloudSync/Components/InsightsTable/components → common/table}/EmptyState.js +0 -0
- data/webpack/common/table/helpers.js +7 -0
- metadata +49 -4
@@ -0,0 +1,60 @@
|
|
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
|
+
aria-label={__('Please enable lab features to use this button')}
|
38
|
+
bodyContent={
|
39
|
+
<div dangerouslySetInnerHTML={{ __html: popoverContent }} />
|
40
|
+
}
|
41
|
+
>
|
42
|
+
{button}
|
43
|
+
</Popover>
|
44
|
+
);
|
45
|
+
}
|
46
|
+
return button;
|
47
|
+
};
|
48
|
+
|
49
|
+
RemediateButton.propTypes = {
|
50
|
+
selectedIds: PropTypes.object,
|
51
|
+
isExperimentalMode: PropTypes.bool,
|
52
|
+
toggleModal: PropTypes.func.isRequired,
|
53
|
+
};
|
54
|
+
|
55
|
+
RemediateButton.defaultProps = {
|
56
|
+
selectedIds: {},
|
57
|
+
isExperimentalMode: false,
|
58
|
+
};
|
59
|
+
|
60
|
+
export default RemediateButton;
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { get } from 'foremanReact/redux/API';
|
2
|
+
import {
|
3
|
+
REMEDIATIONS_API_KEY,
|
4
|
+
REMEDIATIONS_PATH,
|
5
|
+
} from './RemediationTableConstants';
|
6
|
+
|
7
|
+
export const fetchRemediations = ({ selectedIds, isAllSelected, query }) =>
|
8
|
+
get({
|
9
|
+
key: REMEDIATIONS_API_KEY,
|
10
|
+
url: REMEDIATIONS_PATH,
|
11
|
+
params: { ids: Object.keys(selectedIds), isAllSelected, query },
|
12
|
+
});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
/* eslint-disable camelcase */
|
2
|
+
import React from 'react';
|
3
|
+
import { orderBy } from 'lodash';
|
4
|
+
import Resolutions from './Resolutions';
|
5
|
+
|
6
|
+
export const modifyRows = (remediations, setResolutions, setHostsIds) => {
|
7
|
+
if (remediations.length === 0) return [];
|
8
|
+
|
9
|
+
const resolutionToSubmit = [];
|
10
|
+
const hostsIdsToSubmit = new Set();
|
11
|
+
const modifiedRemediations = orderBy(
|
12
|
+
remediations.asMutable(),
|
13
|
+
[r => r.resolutions?.length || 0],
|
14
|
+
['desc']
|
15
|
+
).map(({ id, host_id, hostname, title, resolutions, reboot }) => {
|
16
|
+
hostsIdsToSubmit.add(host_id);
|
17
|
+
const selectedResolution = resolutions[0]?.id;
|
18
|
+
resolutionToSubmit.push({
|
19
|
+
hit_id: id,
|
20
|
+
resolution_id: selectedResolution /** defaults to the first resolution if many */,
|
21
|
+
});
|
22
|
+
return {
|
23
|
+
cells: [
|
24
|
+
hostname,
|
25
|
+
title,
|
26
|
+
<div>
|
27
|
+
<Resolutions
|
28
|
+
hit_id={id}
|
29
|
+
resolutions={resolutions}
|
30
|
+
setResolutions={setResolutions}
|
31
|
+
selectedResolution={selectedResolution}
|
32
|
+
/>
|
33
|
+
</div>,
|
34
|
+
reboot,
|
35
|
+
],
|
36
|
+
id,
|
37
|
+
};
|
38
|
+
});
|
39
|
+
|
40
|
+
setResolutions(resolutionToSubmit);
|
41
|
+
setHostsIds(Array.from(hostsIdsToSubmit));
|
42
|
+
return modifiedRemediations;
|
43
|
+
};
|
@@ -0,0 +1,101 @@
|
|
1
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
2
|
+
import React, { useEffect } from 'react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { Table, TableHeader, TableBody } from '@patternfly/react-table';
|
5
|
+
import { Modal, ModalVariant } from '@patternfly/react-core';
|
6
|
+
import { STATUS } from 'foremanReact/constants';
|
7
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
8
|
+
import { columns } from './RemediationTableConstants';
|
9
|
+
import { modifyRows } from './RemediationHelpers';
|
10
|
+
import ModalFooter from './RemediationModalFooter';
|
11
|
+
import TableEmptyState from '../../../common/table/EmptyState';
|
12
|
+
import './RemediationModal.scss';
|
13
|
+
import RemediateButton from './RemediateButton';
|
14
|
+
|
15
|
+
const RemediationModal = ({
|
16
|
+
selectedIds,
|
17
|
+
fetchRemediations,
|
18
|
+
remediations,
|
19
|
+
status,
|
20
|
+
error,
|
21
|
+
isAllSelected,
|
22
|
+
query,
|
23
|
+
isExperimentalMode,
|
24
|
+
}) => {
|
25
|
+
const [rows, setRows] = React.useState([]);
|
26
|
+
const [open, setOpen] = React.useState(false);
|
27
|
+
const [resolutions, setResolutions] = React.useState([]);
|
28
|
+
const [hostsIds, setHostsIds] = React.useState([]);
|
29
|
+
const toggleModal = () => setOpen(prevValue => !prevValue);
|
30
|
+
|
31
|
+
useEffect(() => {
|
32
|
+
if (open) fetchRemediations({ selectedIds, isAllSelected, query });
|
33
|
+
}, [open]);
|
34
|
+
|
35
|
+
useEffect(() => {
|
36
|
+
const modifiedRows =
|
37
|
+
status === STATUS.PENDING
|
38
|
+
? []
|
39
|
+
: modifyRows(remediations, setResolutions, setHostsIds);
|
40
|
+
setRows(modifiedRows);
|
41
|
+
}, [remediations, status]);
|
42
|
+
|
43
|
+
return (
|
44
|
+
<React.Fragment>
|
45
|
+
<RemediateButton
|
46
|
+
isExperimentalMode={isExperimentalMode}
|
47
|
+
selectedIds={selectedIds}
|
48
|
+
toggleModal={toggleModal}
|
49
|
+
/>{' '}
|
50
|
+
<Modal
|
51
|
+
id="remediation-modal"
|
52
|
+
appendTo={document.body}
|
53
|
+
variant={ModalVariant.large}
|
54
|
+
title={__('Remediation summary')}
|
55
|
+
isOpen={open}
|
56
|
+
onClose={toggleModal}
|
57
|
+
footer={
|
58
|
+
<ModalFooter
|
59
|
+
toggleModal={toggleModal}
|
60
|
+
resolutions={resolutions}
|
61
|
+
hostsIds={hostsIds}
|
62
|
+
/>
|
63
|
+
}
|
64
|
+
>
|
65
|
+
<Table
|
66
|
+
className="remediations-table"
|
67
|
+
aria-label="remediations Table"
|
68
|
+
cells={columns}
|
69
|
+
rows={rows}
|
70
|
+
>
|
71
|
+
<TableHeader />
|
72
|
+
<TableBody />
|
73
|
+
</Table>
|
74
|
+
<TableEmptyState status={status} error={error} />
|
75
|
+
</Modal>
|
76
|
+
</React.Fragment>
|
77
|
+
);
|
78
|
+
};
|
79
|
+
|
80
|
+
RemediationModal.propTypes = {
|
81
|
+
selectedIds: PropTypes.object,
|
82
|
+
fetchRemediations: PropTypes.func.isRequired,
|
83
|
+
remediations: PropTypes.array,
|
84
|
+
status: PropTypes.string,
|
85
|
+
error: PropTypes.string,
|
86
|
+
isAllSelected: PropTypes.bool,
|
87
|
+
query: PropTypes.string,
|
88
|
+
isExperimentalMode: PropTypes.bool,
|
89
|
+
};
|
90
|
+
|
91
|
+
RemediationModal.defaultProps = {
|
92
|
+
selectedIds: {},
|
93
|
+
remediations: [],
|
94
|
+
status: null,
|
95
|
+
error: null,
|
96
|
+
isAllSelected: false,
|
97
|
+
query: null,
|
98
|
+
isExperimentalMode: false,
|
99
|
+
};
|
100
|
+
|
101
|
+
export default RemediationModal;
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { Button } from '@patternfly/react-core';
|
4
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
5
|
+
import { JOB_INVOCATION_PATH } from './RemediationTableConstants';
|
6
|
+
|
7
|
+
const ModalFooter = ({ toggleModal, resolutions, hostsIds }) => {
|
8
|
+
let token = document.querySelector('meta[name="csrf-token"]');
|
9
|
+
token = token?.content || '';
|
10
|
+
return (
|
11
|
+
<form action={JOB_INVOCATION_PATH} method="post">
|
12
|
+
<Button type="submit" key="confirm" variant="primary">
|
13
|
+
{__('Remediate')}
|
14
|
+
</Button>
|
15
|
+
<Button key="cancel" variant="link" onClick={toggleModal}>
|
16
|
+
{__('Cancel')}
|
17
|
+
</Button>
|
18
|
+
<input type="hidden" name="feature" value="rh_cloud_remediate_hosts" />
|
19
|
+
<input type="hidden" name="authenticity_token" value={token} />
|
20
|
+
<input
|
21
|
+
type="hidden"
|
22
|
+
name="inputs[hit_remediation_pairs]"
|
23
|
+
value={JSON.stringify(resolutions)}
|
24
|
+
/>
|
25
|
+
{hostsIds.map(id => (
|
26
|
+
<input type="hidden" name="host_ids[]" key={id} value={id} />
|
27
|
+
))}
|
28
|
+
</form>
|
29
|
+
);
|
30
|
+
};
|
31
|
+
|
32
|
+
ModalFooter.propTypes = {
|
33
|
+
toggleModal: PropTypes.func.isRequired,
|
34
|
+
resolutions: PropTypes.array,
|
35
|
+
hostsIds: PropTypes.array,
|
36
|
+
};
|
37
|
+
|
38
|
+
ModalFooter.defaultProps = {
|
39
|
+
resolutions: [],
|
40
|
+
hostsIds: [],
|
41
|
+
};
|
42
|
+
|
43
|
+
export default ModalFooter;
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { cellWidth } from '@patternfly/react-table';
|
3
|
+
import { CheckCircleIcon } from '@patternfly/react-icons';
|
4
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
5
|
+
import { foremanUrl } from '../../../ForemanRhCloudHelpers';
|
6
|
+
|
7
|
+
export const rebootFormatter = ({ title: reboot }) => ({
|
8
|
+
children: reboot ? <CheckCircleIcon color="green" /> : __('No'),
|
9
|
+
});
|
10
|
+
|
11
|
+
export const columns = [
|
12
|
+
{
|
13
|
+
sortKey: 'hostname',
|
14
|
+
title: __('Hostname'),
|
15
|
+
transforms: [cellWidth(20)],
|
16
|
+
},
|
17
|
+
{
|
18
|
+
title: __('Recommendation'),
|
19
|
+
transforms: [cellWidth(35)],
|
20
|
+
},
|
21
|
+
{
|
22
|
+
title: __('Resolution'),
|
23
|
+
transforms: [cellWidth(30)],
|
24
|
+
},
|
25
|
+
{
|
26
|
+
title: __('Reboot Required'),
|
27
|
+
transforms: [cellWidth(15)],
|
28
|
+
cellTransforms: [rebootFormatter],
|
29
|
+
},
|
30
|
+
];
|
31
|
+
|
32
|
+
export const REMEDIATIONS_PATH = foremanUrl('/insights_cloud/hits/resolutions');
|
33
|
+
|
34
|
+
export const JOB_INVOCATION_PATH = foremanUrl('/job_invocations/new');
|
35
|
+
|
36
|
+
export const REMEDIATIONS_API_KEY = 'INSIGHTS_REMEDIATIONS';
|
37
|
+
|
38
|
+
export const SUBMIT_RESOLUTIONS = 'SUBMIT_INSIGHTS_RESOLUTIONS';
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/* eslint-disable camelcase */
|
2
|
+
import React from 'react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { Radio } from '@patternfly/react-core';
|
5
|
+
|
6
|
+
const Resolutions = ({
|
7
|
+
resolutions,
|
8
|
+
setResolutions,
|
9
|
+
selectedResolution,
|
10
|
+
hit_id,
|
11
|
+
}) => {
|
12
|
+
const [checkedID, setCheckedID] = React.useState(selectedResolution);
|
13
|
+
|
14
|
+
if (resolutions.length === 1) return <>{resolutions[0].description}</>;
|
15
|
+
|
16
|
+
return (
|
17
|
+
<>
|
18
|
+
{resolutions.map(({ id: resolution_id, description }) => (
|
19
|
+
<Radio
|
20
|
+
key={resolution_id}
|
21
|
+
className="resolution-radio"
|
22
|
+
id={resolution_id}
|
23
|
+
isChecked={resolution_id === checkedID}
|
24
|
+
onChange={() =>
|
25
|
+
setResolutions(stateRes =>
|
26
|
+
stateRes.map(res => {
|
27
|
+
if (hit_id === res.hit_id) {
|
28
|
+
setCheckedID(resolution_id);
|
29
|
+
return { ...res, resolution_id };
|
30
|
+
}
|
31
|
+
return res;
|
32
|
+
})
|
33
|
+
)
|
34
|
+
}
|
35
|
+
label={description}
|
36
|
+
/>
|
37
|
+
))}
|
38
|
+
</>
|
39
|
+
);
|
40
|
+
};
|
41
|
+
|
42
|
+
Resolutions.propTypes = {
|
43
|
+
setResolutions: PropTypes.func.isRequired,
|
44
|
+
resolutions: PropTypes.array,
|
45
|
+
hit_id: PropTypes.number,
|
46
|
+
selectedResolution: PropTypes.number,
|
47
|
+
};
|
48
|
+
|
49
|
+
Resolutions.defaultProps = {
|
50
|
+
resolutions: [],
|
51
|
+
hit_id: null,
|
52
|
+
selectedResolution: null,
|
53
|
+
};
|
54
|
+
|
55
|
+
export default Resolutions;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { bindActionCreators } from 'redux';
|
2
|
+
import { connect } from 'react-redux';
|
3
|
+
import {
|
4
|
+
selectAPIResponse,
|
5
|
+
selectAPIStatus,
|
6
|
+
selectAPIErrorMessage,
|
7
|
+
} from 'foremanReact/redux/API/APISelectors';
|
8
|
+
import * as actions from './RemediationActions';
|
9
|
+
import RemediationModal from './RemediationModal';
|
10
|
+
import { REMEDIATIONS_API_KEY } from './RemediationTableConstants';
|
11
|
+
import {
|
12
|
+
selectExperimental,
|
13
|
+
selectIsAllSelected,
|
14
|
+
selectSearch,
|
15
|
+
selectSelectedIds,
|
16
|
+
} from '../InsightsTable/InsightsTableSelectors';
|
17
|
+
|
18
|
+
// map state to props
|
19
|
+
const mapStateToProps = state => ({
|
20
|
+
selectedIds: selectSelectedIds(state),
|
21
|
+
remediations: selectAPIResponse(state, REMEDIATIONS_API_KEY).hits || [],
|
22
|
+
status: selectAPIStatus(state, REMEDIATIONS_API_KEY),
|
23
|
+
error: selectAPIErrorMessage(state, REMEDIATIONS_API_KEY),
|
24
|
+
itemCount: selectAPIResponse(state, REMEDIATIONS_API_KEY).itemCount || 0,
|
25
|
+
isAllSelected: selectIsAllSelected(state),
|
26
|
+
query: selectSearch(state),
|
27
|
+
isExperimentalMode: selectExperimental(state),
|
28
|
+
});
|
29
|
+
|
30
|
+
// map action dispatchers to props
|
31
|
+
const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch);
|
32
|
+
|
33
|
+
// export connected component
|
34
|
+
export default connect(mapStateToProps, mapDispatchToProps)(RemediationModal);
|
data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap
CHANGED
@@ -190,21 +190,28 @@ exports[`NoTokenEmptyState render 1`] = `
|
|
190
190
|
onClick={[Function]}
|
191
191
|
variant="primary"
|
192
192
|
>
|
193
|
-
<
|
194
|
-
|
195
|
-
|
196
|
-
className="pf-c-button pf-m-primary pf-m-disabled"
|
197
|
-
data-ouia-component-id="OUIA-Generated-Button-primary-1"
|
198
|
-
data-ouia-component-type="PF4/Button"
|
199
|
-
data-ouia-safe={true}
|
200
|
-
disabled={true}
|
193
|
+
<ButtonBase
|
194
|
+
innerRef={null}
|
195
|
+
isDisabled={true}
|
201
196
|
onClick={[Function]}
|
202
|
-
|
203
|
-
tabIndex={null}
|
204
|
-
type="button"
|
197
|
+
variant="primary"
|
205
198
|
>
|
206
|
-
|
207
|
-
|
199
|
+
<button
|
200
|
+
aria-disabled={true}
|
201
|
+
aria-label={null}
|
202
|
+
className="pf-c-button pf-m-primary pf-m-disabled"
|
203
|
+
data-ouia-component-id="OUIA-Generated-Button-primary-1"
|
204
|
+
data-ouia-component-type="PF4/Button"
|
205
|
+
data-ouia-safe={true}
|
206
|
+
disabled={true}
|
207
|
+
onClick={[Function]}
|
208
|
+
role={null}
|
209
|
+
tabIndex={null}
|
210
|
+
type="button"
|
211
|
+
>
|
212
|
+
Save setting and sync recommendations
|
213
|
+
</button>
|
214
|
+
</ButtonBase>
|
208
215
|
</Button>
|
209
216
|
</div>
|
210
217
|
</div>
|