foreman_rh_cloud 4.0.24.1 → 4.0.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/rh_cloud/inventory_controller.rb +4 -1
  3. data/app/controllers/foreman_inventory_upload/cloud_status_controller.rb +26 -0
  4. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +18 -4
  5. data/app/controllers/insights_cloud/hits_controller.rb +0 -1
  6. data/app/services/foreman_rh_cloud/cloud_auth.rb +4 -0
  7. data/app/services/foreman_rh_cloud/cloud_ping_service.rb +83 -0
  8. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +15 -3
  9. data/app/services/foreman_rh_cloud/remediations_retriever.rb +5 -0
  10. data/config/Gemfile.lock.gh_test +74 -84
  11. data/config/rh_cert-api_chain.pem +74 -0
  12. data/config/routes.rb +3 -1
  13. data/lib/foreman_inventory_upload/generators/queries.rb +0 -16
  14. data/lib/foreman_inventory_upload/generators/tags.rb +2 -1
  15. data/lib/foreman_rh_cloud/engine.rb +2 -1
  16. data/lib/foreman_rh_cloud/version.rb +1 -1
  17. data/lib/foreman_rh_cloud.rb +16 -1
  18. data/lib/insights_cloud/async/insights_client_status_aging.rb +4 -0
  19. data/lib/insights_cloud/async/insights_full_sync.rb +9 -0
  20. data/lib/insights_cloud/async/insights_generate_notifications.rb +4 -0
  21. data/lib/insights_cloud/async/insights_resolutions_sync.rb +16 -2
  22. data/lib/insights_cloud/async/insights_rules_sync.rb +15 -2
  23. data/lib/insights_cloud.rb +4 -0
  24. data/lib/inventory_sync/async/inventory_full_sync.rb +9 -0
  25. data/lib/inventory_sync/async/inventory_hosts_sync.rb +9 -0
  26. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +4 -0
  27. data/lib/inventory_sync/async/inventory_self_host_sync.rb +13 -0
  28. data/lib/inventory_sync/async/query_inventory_job.rb +4 -0
  29. data/lib/tasks/rh_cloud_inventory.rake +2 -9
  30. data/package.json +1 -1
  31. data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +20 -39
  32. data/test/controllers/inventory_upload/cloud_status_controller_test.rb +44 -0
  33. data/test/jobs/insights_full_sync_test.rb +1 -0
  34. data/test/jobs/insights_resolutions_sync_test.rb +11 -1
  35. data/test/jobs/insights_rules_sync_test.rb +1 -0
  36. data/test/jobs/inventory_full_sync_test.rb +10 -0
  37. data/test/jobs/inventory_hosts_sync_test.rb +1 -0
  38. data/test/jobs/inventory_self_host_sync_test.rb +1 -0
  39. data/test/test_plugin_helper.rb +53 -0
  40. data/test/unit/foreman_rh_cloud_self_host_test.rb +28 -0
  41. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +29 -34
  42. data/test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb +66 -0
  43. data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +1 -0
  44. data/test/unit/tags_generator_test.rb +41 -0
  45. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/EmptyState.js +1 -1
  46. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/EmptyState/__tests__/__snapshots__/EmptyState.test.js.snap +1 -2
  47. data/webpack/ForemanInventoryUpload/Components/FileDownload/FileDownload.js +3 -1
  48. data/webpack/ForemanInventoryUpload/Components/FileDownload/__tests__/__snapshots__/FileDownload.test.js.snap +2 -1
  49. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilter.js +1 -2
  50. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/InventoryFilterConstants.js +3 -1
  51. data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettings.scss +0 -4
  52. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +12 -0
  53. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +10 -0
  54. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +144 -0
  55. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.scss +5 -0
  56. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +2 -2
  57. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Modal.js +1 -1
  58. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/SyncButton/components/Toast.js +2 -2
  59. data/webpack/ForemanInventoryUpload/Components/StatusChart/StatusChart.js +4 -3
  60. data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +2 -0
  61. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/InventoryAutoUpload.js +3 -1
  62. data/webpack/InsightsCloudSync/Components/InsightsHeader/InsightsHeader.scss +5 -1
  63. data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +6 -6
  64. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +9 -5
  65. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +6 -6
  66. data/webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss +1 -14
  67. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +4 -22
  68. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +25 -4
  69. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
  70. data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +51 -0
  71. data/webpack/InsightsCloudSync/Components/InsightsTable/SelectAllAlert.js +1 -1
  72. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +3 -68
  73. data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +10 -0
  74. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +11 -10
  75. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +14 -0
  76. data/webpack/InsightsCloudSync/Components/RemediationModal/index.js +0 -2
  77. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +32 -0
  78. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +5 -5
  79. data/webpack/InsightsCloudSync/InsightsCloudSync.js +19 -13
  80. data/webpack/InsightsCloudSync/InsightsCloudSync.scss +82 -2
  81. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +16 -6
  82. data/webpack/InsightsHostDetailsTab/InsightsTab.js +3 -2
  83. data/webpack/InsightsHostDetailsTab/InsightsTab.scss +4 -4
  84. data/webpack/InsightsHostDetailsTab/components/ListItem/ListItem.js +9 -7
  85. data/webpack/common/Switcher/HelpLabel.js +1 -1
  86. data/webpack/common/Switcher/SwitcherPF4.js +1 -1
  87. data/webpack/common/Switcher/SwitcherPF4.scss +6 -7
  88. data/webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap +1 -1
  89. data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -1
  90. metadata +16 -24
  91. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.fixtures.js +0 -1
  92. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.js +0 -45
  93. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/InsightsSyncSwitcher.test.js +0 -17
  94. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/__snapshots__/InsightsSyncSwitcher.test.js.snap +0 -38
  95. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/index.js +0 -1
  96. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/insightsSyncSwitcher.scss +0 -3
  97. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +0 -59
@@ -4,12 +4,12 @@ exports[`InsightsSettings rendering render without Props 1`] = `
4
4
  <div
5
5
  className="insights_settings"
6
6
  >
7
- <h3>
8
- Settings
9
- </h3>
10
- <InsightsSyncSwitcher
11
- insightsSyncEnabled={false}
12
- setInsightsSyncEnabled={[Function]}
7
+ <SwitcherPF4
8
+ id="insights_sync_switcher"
9
+ isChecked={false}
10
+ label="Sync automatically"
11
+ onChange={[Function]}
12
+ tooltip="Enable automatic synchronization of Insights recommendations from the Red Hat cloud"
13
13
  />
14
14
  </div>
15
15
  `;
@@ -1,17 +1,4 @@
1
1
  .insights_settings {
2
- margin-left: 10px;
3
- border: 1px solid #ededed;
4
- border-radius: 4px;
5
- padding: 10px;
6
- margin-bottom: 15px;
7
2
  float: right;
8
-
9
- h3 {
10
- margin-top: 0;
11
- font-weight: 600;
12
- }
13
-
14
- .bootstrap-switch {
15
- float: right;
16
- }
3
+ margin-top: 22px;
17
4
  }
@@ -1,17 +1,13 @@
1
1
  /* eslint-disable react-hooks/exhaustive-deps */
2
2
  import React, { useEffect } from 'react';
3
3
  import PropTypes from 'prop-types';
4
- import { Pagination, PaginationVariant } from '@patternfly/react-core';
5
4
  import { Table, TableHeader, TableBody } from '@patternfly/react-table';
6
5
  import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
7
6
  import SelectAllAlert from './SelectAllAlert';
8
7
  import { columns } from './InsightsTableConstants';
9
8
  import TableEmptyState from '../../../common/table/EmptyState';
10
- import {
11
- modifySelectedRows,
12
- getSortColumnIndex,
13
- getPerPageOptions,
14
- } from './InsightsTableHelpers';
9
+ import { modifySelectedRows, getSortColumnIndex } from './InsightsTableHelpers';
10
+ import Pagination from './Pagination';
15
11
  import './table.scss';
16
12
 
17
13
  const InsightsTable = ({
@@ -22,10 +18,7 @@ const InsightsTable = ({
22
18
  sortOrder,
23
19
  hits,
24
20
  query,
25
- itemCount,
26
21
  fetchInsights,
27
- onTableSetPage,
28
- onTablePerPageSelect,
29
22
  onTableSort,
30
23
  onTableSelect,
31
24
  selectedIds,
@@ -68,21 +61,13 @@ const InsightsTable = ({
68
61
  onSort={onTableSort}
69
62
  cells={columns}
70
63
  rows={rows}
64
+ variant="compact"
71
65
  >
72
66
  <TableHeader />
73
67
  <TableBody />
74
68
  </Table>
75
69
  <TableEmptyState status={status} error={error} />
76
- <Pagination
77
- itemCount={itemCount}
78
- widgetId="recommendation-pagination"
79
- perPage={perPage}
80
- page={page}
81
- variant={PaginationVariant.bottom}
82
- onSetPage={onTableSetPage}
83
- onPerPageSelect={onTablePerPageSelect}
84
- perPageOptions={getPerPageOptions(urlPerPage, appPerPage)}
85
- />
70
+ <Pagination variant="bottom" />
86
71
  </React.Fragment>
87
72
  );
88
73
  };
@@ -94,9 +79,6 @@ InsightsTable.propTypes = {
94
79
  sortBy: PropTypes.string,
95
80
  sortOrder: PropTypes.string,
96
81
  hits: PropTypes.array.isRequired,
97
- itemCount: PropTypes.number.isRequired,
98
- onTableSetPage: PropTypes.func.isRequired,
99
- onTablePerPageSelect: PropTypes.func.isRequired,
100
82
  onTableSort: PropTypes.func.isRequired,
101
83
  onTableSelect: PropTypes.func.isRequired,
102
84
  selectedIds: PropTypes.object,
@@ -5,7 +5,7 @@ import {
5
5
  Section,
6
6
  } from '@redhat-cloud-services/frontend-components';
7
7
  import { sortable, cellWidth } from '@patternfly/react-table';
8
- import { CheckCircleIcon } from '@patternfly/react-icons';
8
+ import { AnsibeTowerIcon } from '@patternfly/react-icons';
9
9
  import { translate as __ } from 'foremanReact/common/I18n';
10
10
  import { foremanUrl } from '../../../ForemanRhCloudHelpers';
11
11
 
@@ -18,7 +18,14 @@ export const totalRiskFormatter = ({ title: totalRisk }) => ({
18
18
  });
19
19
 
20
20
  export const hasPlaybookFormatter = ({ title: hasPlaybook }) => ({
21
- children: hasPlaybook ? <CheckCircleIcon color="green" /> : __('No'),
21
+ children: hasPlaybook ? (
22
+ <span className="td-insights-remediate-playbook">
23
+ <AnsibeTowerIcon />
24
+ {__('Playbook')}
25
+ </span>
26
+ ) : (
27
+ <span className="td-insights-remediate-manual">{__('Manual')}</span>
28
+ ),
22
29
  });
23
30
 
24
31
  export const columns = [
@@ -34,17 +41,31 @@ export const columns = [
34
41
  },
35
42
  {
36
43
  sortKey: 'total_risk',
37
- title: __('Total Risk'),
44
+ title: __('Total risk'),
38
45
  transforms: [cellWidth(15), sortable],
39
46
  cellTransforms: [totalRiskFormatter],
40
47
  },
41
48
  {
42
- title: __('Playbook'),
49
+ title: __('Remediate'),
43
50
  transforms: [cellWidth(15)],
44
51
  cellTransforms: [hasPlaybookFormatter],
45
52
  },
46
53
  ];
47
54
 
55
+ export const paginationTitles = {
56
+ items: __('items'),
57
+ page: __('page'),
58
+ itemsPerPage: __('Items per page'),
59
+ perPageSuffix: __('per page'),
60
+ toFirstPage: __('Go to first page'),
61
+ toPreviousPage: __('Go to previous page'),
62
+ toLastPage: __('Go to last page'),
63
+ toNextPage: __('Go to next page'),
64
+ optionsToggle: __('Items per page'),
65
+ currPage: __('Current page'),
66
+ paginationTitle: __('Pagination'),
67
+ };
68
+
48
69
  export const INSIGHTS_HITS_PATH = foremanUrl('/insights_cloud/hits');
49
70
 
50
71
  export const INSIGHTS_HITS_API_KEY = 'INSIGHTS_HITS';
@@ -76,6 +76,3 @@ export const selectItemCount = state =>
76
76
 
77
77
  export const selectHasToken = state =>
78
78
  selectAPIResponse(state, INSIGHTS_HITS_API_KEY).hasToken;
79
-
80
- export const selectExperimental = state =>
81
- selectAPIResponse(state, INSIGHTS_HITS_API_KEY).isExperimentalMode;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useDispatch, useSelector } from 'react-redux';
4
+ import {
5
+ Pagination as PfPagination,
6
+ PaginationVariant,
7
+ } from '@patternfly/react-core';
8
+ import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
9
+ import { onTablePerPageSelect, onTableSetPage } from './InsightsTableActions';
10
+ import { getPerPageOptions } from './InsightsTableHelpers';
11
+ import {
12
+ selectItemCount,
13
+ selectPage,
14
+ selectPerPage,
15
+ } from './InsightsTableSelectors';
16
+
17
+ const Pagination = ({ variant, ...props }) => {
18
+ const dispatch = useDispatch();
19
+ const onSetPage = (e, pageNumber) => dispatch(onTableSetPage(e, pageNumber));
20
+ const onPerPageSelect = (e, perPageNumber) =>
21
+ dispatch(onTablePerPageSelect(e, perPageNumber));
22
+ const itemCount = useSelector(state => selectItemCount(state));
23
+ const urlPerPage = useSelector(state => selectPerPage(state));
24
+ const page = useSelector(state => selectPage(state));
25
+ const { perPage: appPerPage } = useForemanSettings();
26
+ const perPage = urlPerPage || appPerPage;
27
+
28
+ return (
29
+ <PfPagination
30
+ itemCount={itemCount}
31
+ widgetId={`recommendation-pagination-${variant}`}
32
+ perPage={perPage}
33
+ page={page}
34
+ variant={PaginationVariant[variant]}
35
+ onSetPage={onSetPage}
36
+ onPerPageSelect={onPerPageSelect}
37
+ perPageOptions={getPerPageOptions(urlPerPage, appPerPage)}
38
+ {...props}
39
+ />
40
+ );
41
+ };
42
+
43
+ Pagination.propTypes = {
44
+ variant: PropTypes.string,
45
+ };
46
+
47
+ Pagination.defaultProps = {
48
+ variant: 'top',
49
+ };
50
+
51
+ export default Pagination;
@@ -18,7 +18,7 @@ const SelectAllAlert = ({
18
18
  <Alert
19
19
  isInline
20
20
  variant="info"
21
- title={sprintf('Recommendations selected: %s.', selectedCount)}
21
+ title={sprintf(__('Recommendations selected: %s.'), selectedCount)}
22
22
  actionLinks={
23
23
  <AlertActionLink onClick={selectAll}>
24
24
  {__('Select recommendations from all pages')}
@@ -37,7 +37,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
37
37
  [Function],
38
38
  ],
39
39
  "sortKey": "total_risk",
40
- "title": "Total Risk",
40
+ "title": "Total risk",
41
41
  "transforms": Array [
42
42
  [Function],
43
43
  [Function],
@@ -47,7 +47,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
47
47
  "cellTransforms": Array [
48
48
  [Function],
49
49
  ],
50
- "title": "Playbook",
50
+ "title": "Remediate",
51
51
  "transforms": Array [
52
52
  [Function],
53
53
  ],
@@ -74,7 +74,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
74
74
  "index": 3,
75
75
  }
76
76
  }
77
- variant={null}
77
+ variant="compact"
78
78
  >
79
79
  <TableHeader />
80
80
  <Component />
@@ -84,72 +84,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
84
84
  status="RESOLVED"
85
85
  />
86
86
  <Pagination
87
- className=""
88
- defaultToFullPage={false}
89
- firstPage={1}
90
- isCompact={false}
91
- isDisabled={false}
92
- isSticky={false}
93
- itemCount={2}
94
- itemsEnd={null}
95
- itemsStart={null}
96
- offset={0}
97
- onFirstClick={[Function]}
98
- onLastClick={[Function]}
99
- onNextClick={[Function]}
100
- onPageInput={[Function]}
101
- onPerPageSelect={[Function]}
102
- onPreviousClick={[Function]}
103
- onSetPage={[Function]}
104
- ouiaSafe={true}
105
- page={1}
106
- perPage={5}
107
- perPageOptions={
108
- Array [
109
- Object {
110
- "title": "5",
111
- "value": 5,
112
- },
113
- Object {
114
- "title": "10",
115
- "value": 10,
116
- },
117
- Object {
118
- "title": "15",
119
- "value": 15,
120
- },
121
- Object {
122
- "title": "20",
123
- "value": 20,
124
- },
125
- Object {
126
- "title": "25",
127
- "value": 25,
128
- },
129
- Object {
130
- "title": "50",
131
- "value": 50,
132
- },
133
- ]
134
- }
135
- titles={
136
- Object {
137
- "currPage": "Current page",
138
- "items": "",
139
- "itemsPerPage": "Items per page",
140
- "optionsToggle": "Items per page",
141
- "page": "",
142
- "paginationTitle": "Pagination",
143
- "perPageSuffix": "per page",
144
- "toFirstPage": "Go to first page",
145
- "toLastPage": "Go to last page",
146
- "toNextPage": "Go to next page",
147
- "toPreviousPage": "Go to previous page",
148
- }
149
- }
150
- toggleTemplate={[Function]}
151
87
  variant="bottom"
152
- widgetId="recommendation-pagination"
153
88
  />
154
89
  </Fragment>
155
90
  `;
@@ -7,5 +7,15 @@
7
7
  display: none;
8
8
  }
9
9
  }
10
+
11
+ .td-insights-remediate-playbook {
12
+ svg {
13
+ margin-right: 5px;
14
+ }
15
+ }
16
+
17
+ .td-insights-remediate-manual {
18
+ padding-left: 18px;
19
+ }
10
20
  }
11
21
  }
@@ -2,7 +2,8 @@
2
2
  import React, { useEffect } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import { Table, TableHeader, TableBody } from '@patternfly/react-table';
5
- import { Modal, ModalVariant } from '@patternfly/react-core';
5
+ import { Modal, ModalVariant, Button } from '@patternfly/react-core';
6
+ import { isEmpty } from 'lodash';
6
7
  import { STATUS } from 'foremanReact/constants';
7
8
  import { translate as __ } from 'foremanReact/common/I18n';
8
9
  import { columns } from './RemediationTableConstants';
@@ -10,7 +11,6 @@ import { modifyRows } from './RemediationHelpers';
10
11
  import ModalFooter from './RemediationModalFooter';
11
12
  import TableEmptyState from '../../../common/table/EmptyState';
12
13
  import './RemediationModal.scss';
13
- import RemediateButton from './RemediateButton';
14
14
 
15
15
  const RemediationModal = ({
16
16
  selectedIds,
@@ -20,7 +20,6 @@ const RemediationModal = ({
20
20
  error,
21
21
  isAllSelected,
22
22
  query,
23
- isExperimentalMode,
24
23
  }) => {
25
24
  const [rows, setRows] = React.useState([]);
26
25
  const [open, setOpen] = React.useState(false);
@@ -42,11 +41,15 @@ const RemediationModal = ({
42
41
 
43
42
  return (
44
43
  <React.Fragment>
45
- <RemediateButton
46
- isExperimentalMode={isExperimentalMode}
47
- selectedIds={selectedIds}
48
- toggleModal={toggleModal}
49
- />{' '}
44
+ <Button
45
+ variant="primary"
46
+ isDisabled={isEmpty(selectedIds)}
47
+ onClick={() => {
48
+ toggleModal();
49
+ }}
50
+ >
51
+ {__('Remediate')}
52
+ </Button>{' '}
50
53
  <Modal
51
54
  id="remediation-modal"
52
55
  appendTo={document.body}
@@ -85,7 +88,6 @@ RemediationModal.propTypes = {
85
88
  error: PropTypes.string,
86
89
  isAllSelected: PropTypes.bool,
87
90
  query: PropTypes.string,
88
- isExperimentalMode: PropTypes.bool,
89
91
  };
90
92
 
91
93
  RemediationModal.defaultProps = {
@@ -95,7 +97,6 @@ RemediationModal.defaultProps = {
95
97
  error: null,
96
98
  isAllSelected: false,
97
99
  query: null,
98
- isExperimentalMode: false,
99
100
  };
100
101
 
101
102
  export default RemediationModal;
@@ -6,4 +6,18 @@
6
6
  margin-top: 5px;
7
7
  }
8
8
  }
9
+
10
+ // applies to the backdrop parent of the modal
11
+ @at-root .pf-c-backdrop {
12
+ width: calc(100% - 200px);
13
+ left: 200px;
14
+ }
15
+
16
+ // where the vertical nav breaks: https://github.com/theforeman/foreman/blob/3347fa49d500964f0209122d8d36c920d1feafcc/webpack/assets/javascripts/react_app/components/Layout/components/Toolbar/HeaderToolbar.scss#L26
17
+ @media (max-width: 768px) {
18
+ @at-root .pf-c-backdrop {
19
+ width: 100%;
20
+ left: 0;
21
+ }
22
+ }
9
23
  }
@@ -9,7 +9,6 @@ import * as actions from './RemediationActions';
9
9
  import RemediationModal from './RemediationModal';
10
10
  import { REMEDIATIONS_API_KEY } from './RemediationTableConstants';
11
11
  import {
12
- selectExperimental,
13
12
  selectIsAllSelected,
14
13
  selectSearch,
15
14
  selectSelectedIds,
@@ -24,7 +23,6 @@ const mapStateToProps = state => ({
24
23
  itemCount: selectAPIResponse(state, REMEDIATIONS_API_KEY).itemCount || 0,
25
24
  isAllSelected: selectIsAllSelected(state),
26
25
  query: selectSearch(state),
27
- isExperimentalMode: selectExperimental(state),
28
26
  });
29
27
 
30
28
  // map action dispatchers to props
@@ -0,0 +1,32 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import { Dropdown, DropdownItem, KebabToggle } from '@patternfly/react-core';
5
+
6
+ const ToolbarDropdown = ({ onRecommendationSync }) => {
7
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
8
+ const dropdownItems = [
9
+ <DropdownItem
10
+ key="recommendation-manual-sync"
11
+ onClick={onRecommendationSync}
12
+ >
13
+ {__('Sync recommendations')}
14
+ </DropdownItem>,
15
+ ];
16
+ return (
17
+ <Dropdown
18
+ className="title-dropdown"
19
+ onSelect={() => setIsDropdownOpen(false)}
20
+ toggle={<KebabToggle onToggle={isOpen => setIsDropdownOpen(isOpen)} />}
21
+ isOpen={isDropdownOpen}
22
+ isPlain
23
+ dropdownItems={dropdownItems}
24
+ />
25
+ );
26
+ };
27
+
28
+ ToolbarDropdown.propTypes = {
29
+ onRecommendationSync: PropTypes.func.isRequired,
30
+ };
31
+
32
+ export default ToolbarDropdown;
@@ -4,10 +4,10 @@ exports[`InsightsHeader render 1`] = `
4
4
  <div
5
5
  className="insights-header"
6
6
  >
7
- <Connect(InsightsSettings) />
8
- <p>
9
- Insights synchronization process is used to provide Insights
10
- recommendations output for hosts managed here
11
- </p>
7
+ <Text
8
+ component="p"
9
+ >
10
+ Insights synchronization process is used to provide Insights recommendations output for hosts managed here.
11
+ </Text>
12
12
  </div>
13
13
  `;
@@ -1,7 +1,5 @@
1
1
  import React from 'react';
2
- import { Button } from '@patternfly/react-core';
3
2
  import PropTypes from 'prop-types';
4
- import { translate as __ } from 'foremanReact/common/I18n';
5
3
  import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
6
4
  import InsightsHeader from './Components/InsightsHeader';
7
5
  import { NoTokenEmptyState } from './Components/NoTokenEmptyState';
@@ -12,6 +10,9 @@ import {
12
10
  INSIGHTS_SEARCH_PROPS,
13
11
  } from './InsightsCloudSyncConstants';
14
12
  import './InsightsCloudSync.scss';
13
+ import Pagination from './Components/InsightsTable/Pagination';
14
+ import ToolbarDropdown from './Components/ToolbarDropdown';
15
+ import InsightsSettings from './Components/InsightsSettings';
15
16
 
16
17
  const InsightsCloudSync = ({
17
18
  syncInsights,
@@ -26,24 +27,29 @@ const InsightsCloudSync = ({
26
27
  </PageLayout>
27
28
  );
28
29
  }
30
+
31
+ const onRecommendationSync = () => syncInsights(fetchInsights, query);
32
+ const toolbarButtons = (
33
+ <>
34
+ <span className="insights-toolbar-buttons">
35
+ <RemediationModal />
36
+ <ToolbarDropdown onRecommendationSync={onRecommendationSync} />
37
+ </span>
38
+ <span className="pull-right">
39
+ <Pagination variant="top" isCompact />
40
+ </span>
41
+ </>
42
+ );
43
+
29
44
  return (
30
45
  <div className="rh-cloud-insights">
46
+ <InsightsSettings />
31
47
  <PageLayout
32
48
  searchable
33
49
  searchProps={INSIGHTS_SEARCH_PROPS}
34
50
  onSearch={nextQuery => fetchInsights({ query: nextQuery, page: 1 })}
35
51
  header={INSIGHTS_SYNC_PAGE_TITLE}
36
- toolbarButtons={
37
- <>
38
- <RemediationModal />
39
- <Button
40
- variant="secondary"
41
- onClick={() => syncInsights(fetchInsights, query)}
42
- >
43
- {__('Start recommendations sync')}
44
- </Button>
45
- </>
46
- }
52
+ toolbarButtons={toolbarButtons}
47
53
  searchQuery={query}
48
54
  beforeToolbarComponent={<InsightsHeader />}
49
55
  >
@@ -1,5 +1,85 @@
1
1
  .rh-cloud-insights {
2
- .btn-toolbar {
3
- display: inherit;
2
+ #main {
3
+ padding: 4px;
4
+
5
+ #breadcrumb .form-group {
6
+ margin-bottom: 0;
7
+
8
+ h1 {
9
+ font-family: 'RedHatDisplay';
10
+ font-weight: 400;
11
+ margin-bottom: 8px;
12
+ }
13
+ }
14
+
15
+ .title_filter {
16
+ width: 520px;
17
+ }
18
+
19
+ #title_action {
20
+ width: calc(100% - 520px);
21
+ }
22
+
23
+ @media (max-width: 1138px) {
24
+ #title_action {
25
+ width: 70%;
26
+ }
27
+ }
28
+
29
+ .search-bar {
30
+ // Giving pf3 search bar a pf4 look
31
+ width: 500px;
32
+ .search-bar {
33
+ display: block;
34
+ }
35
+ .input-group {
36
+ display: table;
37
+ }
38
+ .input-group-btn {
39
+ .btn-group {
40
+ z-index: unset; // so the bookmarks drop down will be above other search boxes
41
+ }
42
+ .autocomplete-search-btn {
43
+ display: none;
44
+ }
45
+ .dropdown-toggle {
46
+ font-size: 16px;
47
+ background-color: white;
48
+ background-image: none;
49
+ padding-bottom: 4px;
50
+ padding-top: 4px;
51
+ }
52
+ .scrollable-dropdown {
53
+ max-width: 250px;
54
+ }
55
+ }
56
+ li {
57
+ font-size: 16px;
58
+ }
59
+ input {
60
+ font-size: 16px;
61
+ height: 36px;
62
+ }
63
+ .foreman-autocomplete .autocomplete-focus-shortcut {
64
+ top: 8px;
65
+ font-size: 16px;
66
+ }
67
+ .foreman-autocomplete .autocomplete-aux {
68
+ top: 8px;
69
+ font-size: 16px;
70
+ .autocomplete-clear-button {
71
+ font-size: 16px;
72
+ }
73
+ }
74
+ }
75
+
76
+ .btn-toolbar {
77
+ display: inherit;
78
+ width: 100%;
79
+ }
80
+
81
+ .pf-c-pagination {
82
+ padding-right: 0;
83
+ }
4
84
  }
5
85
  }
@@ -4,6 +4,7 @@ exports[`InsightsCloudSync render 1`] = `
4
4
  <div
5
5
  className="rh-cloud-insights"
6
6
  >
7
+ <Connect(InsightsSettings) />
7
8
  <PageLayout
8
9
  beforeToolbarComponent={<InsightsHeader />}
9
10
  header="Red Hat Insights"
@@ -28,13 +29,22 @@ exports[`InsightsCloudSync render 1`] = `
28
29
  searchable={true}
29
30
  toolbarButtons={
30
31
  <React.Fragment>
31
- <UNDEFINED />
32
- <Button
33
- onClick={[Function]}
34
- variant="secondary"
32
+ <span
33
+ className="insights-toolbar-buttons"
35
34
  >
36
- Start recommendations sync
37
- </Button>
35
+ <UNDEFINED />
36
+ <ToolbarDropdown
37
+ onRecommendationSync={[Function]}
38
+ />
39
+ </span>
40
+ <span
41
+ className="pull-right"
42
+ >
43
+ <Pagination
44
+ isCompact={true}
45
+ variant="top"
46
+ />
47
+ </span>
38
48
  </React.Fragment>
39
49
  }
40
50
  >