foreman_rh_cloud 4.0.25 → 5.0.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/rh_cloud/inventory_controller.rb +4 -1
  3. data/app/controllers/concerns/inventory_upload/report_actions.rb +1 -1
  4. data/app/controllers/foreman_inventory_upload/cloud_status_controller.rb +26 -0
  5. data/app/controllers/foreman_inventory_upload/reports_controller.rb +1 -1
  6. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +18 -4
  7. data/app/controllers/insights_cloud/hits_controller.rb +0 -1
  8. data/app/models/setting/rh_cloud.rb +0 -1
  9. data/app/models/task_output_line.rb +2 -0
  10. data/app/models/task_output_status.rb +2 -0
  11. data/app/services/foreman_rh_cloud/cloud_ping_service.rb +83 -0
  12. data/app/services/foreman_rh_cloud/cloud_request_forwarder.rb +15 -3
  13. data/config/Gemfile.lock.gh_test +169 -160
  14. data/config/database.yml.example +2 -2
  15. data/config/package-lock.json.plugin +10551 -7500
  16. data/config/rh_cert-api_chain.pem +74 -0
  17. data/config/routes.rb +3 -1
  18. data/db/migrate/20211027000001_create_task_output.foreman_rh_cloud.rb +18 -0
  19. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +11 -7
  20. data/lib/foreman_inventory_upload/async/generate_report_job.rb +24 -12
  21. data/lib/foreman_inventory_upload/async/progress_output.rb +5 -28
  22. data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +20 -5
  23. data/lib/foreman_inventory_upload/async/shell_process.rb +17 -4
  24. data/lib/foreman_inventory_upload/async/upload_report_job.rb +22 -13
  25. data/lib/foreman_inventory_upload/generators/queries.rb +0 -16
  26. data/lib/foreman_inventory_upload/generators/tags.rb +1 -2
  27. data/lib/foreman_rh_cloud/engine.rb +4 -11
  28. data/lib/foreman_rh_cloud/version.rb +1 -1
  29. data/lib/foreman_rh_cloud.rb +16 -1
  30. data/lib/insights_cloud/async/insights_client_status_aging.rb +4 -0
  31. data/lib/insights_cloud/async/insights_full_sync.rb +4 -0
  32. data/lib/insights_cloud/async/insights_generate_notifications.rb +4 -0
  33. data/lib/insights_cloud/async/insights_resolutions_sync.rb +7 -2
  34. data/lib/insights_cloud/async/insights_rules_sync.rb +10 -2
  35. data/lib/insights_cloud/async/insights_scheduled_sync.rb +11 -7
  36. data/lib/insights_cloud.rb +4 -0
  37. data/lib/inventory_sync/async/inventory_full_sync.rb +4 -0
  38. data/lib/inventory_sync/async/inventory_hosts_sync.rb +4 -0
  39. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +4 -0
  40. data/lib/inventory_sync/async/inventory_self_host_sync.rb +4 -0
  41. data/lib/inventory_sync/async/query_inventory_job.rb +4 -0
  42. data/lib/tasks/rh_cloud_inventory.rake +4 -11
  43. data/package.json +7 -12
  44. data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +20 -39
  45. data/test/controllers/inventory_upload/cloud_status_controller_test.rb +44 -0
  46. data/test/factories/inventory_upload_factories.rb +14 -0
  47. data/test/jobs/insights_resolutions_sync_test.rb +10 -1
  48. data/test/jobs/upload_report_job_test.rb +5 -3
  49. data/test/test_plugin_helper.rb +53 -0
  50. data/test/unit/foreman_rh_cloud_self_host_test.rb +28 -0
  51. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +29 -34
  52. data/test/unit/services/foreman_rh_cloud/cloud_status_service_test.rb +66 -0
  53. data/test/unit/shell_process_job_test.rb +3 -1
  54. data/test/unit/slice_generator_test.rb +24 -4
  55. data/test/unit/tags_generator_test.rb +16 -16
  56. data/webpack/ForemanInventoryUpload/Components/AccountList/accountList.scss +8 -0
  57. data/webpack/ForemanInventoryUpload/Components/InventorySettings/InventorySettings.scss +0 -4
  58. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.scss +17 -4
  59. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +36 -12
  60. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +58 -37
  61. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.js +144 -0
  62. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/CloudPingModal/index.scss +5 -0
  63. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +12 -10
  64. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +10 -10
  65. data/webpack/ForemanInventoryUpload/ForemanInventoryConstants.js +2 -0
  66. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +1 -1
  67. data/webpack/InsightsCloudSync/Components/InsightsHeader/InsightsHeader.scss +5 -1
  68. data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +6 -6
  69. data/webpack/InsightsCloudSync/Components/InsightsSettings/InsightsSettings.js +9 -5
  70. data/webpack/InsightsCloudSync/Components/InsightsSettings/__tests__/__snapshots__/InsightsSettings.test.js.snap +6 -6
  71. data/webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss +1 -14
  72. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +5 -24
  73. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +11 -4
  74. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors.js +0 -3
  75. data/webpack/InsightsCloudSync/Components/InsightsTable/Pagination.js +51 -0
  76. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +7 -69
  77. data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +10 -0
  78. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +11 -10
  79. data/webpack/InsightsCloudSync/Components/RemediationModal/index.js +0 -2
  80. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +32 -0
  81. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +5 -5
  82. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap +24 -13
  83. data/webpack/InsightsCloudSync/InsightsCloudSync.js +19 -13
  84. data/webpack/InsightsCloudSync/InsightsCloudSync.scss +82 -2
  85. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +16 -6
  86. data/webpack/__mocks__/foremanReact/components/Head.js +11 -0
  87. data/webpack/common/Switcher/HelpLabel.js +1 -1
  88. data/webpack/common/Switcher/SwitcherPF4.js +1 -1
  89. data/webpack/common/Switcher/SwitcherPF4.scss +6 -7
  90. data/webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap +1 -1
  91. data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +2 -1
  92. metadata +20 -24
  93. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.fixtures.js +0 -1
  94. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/InsightsSyncSwitcher.js +0 -45
  95. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/InsightsSyncSwitcher.test.js +0 -17
  96. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/__tests__/__snapshots__/InsightsSyncSwitcher.test.js.snap +0 -38
  97. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/index.js +0 -1
  98. data/webpack/InsightsCloudSync/Components/InsightsSyncSwitcher/insightsSyncSwitcher.scss +0 -3
  99. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediateButton.js +0 -59
@@ -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
- import { columns, paginationTitles } from './InsightsTableConstants';
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,22 +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
- titles={paginationTitles}
86
- />
70
+ <Pagination variant="bottom" />
87
71
  </React.Fragment>
88
72
  );
89
73
  };
@@ -95,9 +79,6 @@ InsightsTable.propTypes = {
95
79
  sortBy: PropTypes.string,
96
80
  sortOrder: PropTypes.string,
97
81
  hits: PropTypes.array.isRequired,
98
- itemCount: PropTypes.number.isRequired,
99
- onTableSetPage: PropTypes.func.isRequired,
100
- onTablePerPageSelect: PropTypes.func.isRequired,
101
82
  onTableSort: PropTypes.func.isRequired,
102
83
  onTableSelect: PropTypes.func.isRequired,
103
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,12 +41,12 @@ 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
  },
@@ -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;
@@ -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
  ],
@@ -60,7 +60,10 @@ exports[`InsightsTable rendering render with Props 1`] = `
60
60
  dropdownPosition="right"
61
61
  expandId="expandable-toggle"
62
62
  gridBreakPoint="grid-md"
63
+ isHeaderSelectDisabled={false}
64
+ isNested={false}
63
65
  isStickyHeader={false}
66
+ isTreeTable={false}
64
67
  onSelect={[Function]}
65
68
  onSort={[Function]}
66
69
  ouiaSafe={true}
@@ -74,82 +77,17 @@ exports[`InsightsTable rendering render with Props 1`] = `
74
77
  "index": 3,
75
78
  }
76
79
  }
77
- variant={null}
80
+ variant="compact"
78
81
  >
79
82
  <TableHeader />
80
- <Component />
83
+ <TableBody />
81
84
  </Table>
82
85
  <TableEmptyState
83
86
  error={null}
84
87
  status="RESOLVED"
85
88
  />
86
89
  <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": "items",
139
- "itemsPerPage": "Items per page",
140
- "optionsToggle": "Items per page",
141
- "page": "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
90
  variant="bottom"
152
- widgetId="recommendation-pagination"
153
91
  />
154
92
  </Fragment>
155
93
  `;
@@ -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;
@@ -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
  `;
@@ -157,6 +157,7 @@ exports[`NoTokenEmptyState render 1`] = `
157
157
  isReadOnly={false}
158
158
  isRequired={false}
159
159
  onChange={[Function]}
160
+ ouiaSafe={true}
160
161
  type="password"
161
162
  validated="default"
162
163
  value=""
@@ -165,6 +166,9 @@ exports[`NoTokenEmptyState render 1`] = `
165
166
  aria-invalid={false}
166
167
  aria-label="input-cloud-token"
167
168
  className="pf-c-form-control"
169
+ data-ouia-component-id="OUIA-Generated-TextInputBase-1"
170
+ data-ouia-component-type="PF4/TextInput"
171
+ data-ouia-safe={true}
168
172
  disabled={false}
169
173
  onBlur={[Function]}
170
174
  onChange={[Function]}
@@ -190,21 +194,28 @@ exports[`NoTokenEmptyState render 1`] = `
190
194
  onClick={[Function]}
191
195
  variant="primary"
192
196
  >
193
- <button
194
- aria-disabled={true}
195
- aria-label={null}
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}
197
+ <ButtonBase
198
+ innerRef={null}
199
+ isDisabled={true}
201
200
  onClick={[Function]}
202
- role={null}
203
- tabIndex={null}
204
- type="button"
201
+ variant="primary"
205
202
  >
206
- Save setting and sync recommendations
207
- </button>
203
+ <button
204
+ aria-disabled={true}
205
+ aria-label={null}
206
+ className="pf-c-button pf-m-primary pf-m-disabled"
207
+ data-ouia-component-id="OUIA-Generated-Button-primary-1"
208
+ data-ouia-component-type="PF4/Button"
209
+ data-ouia-safe={true}
210
+ disabled={true}
211
+ onClick={[Function]}
212
+ role={null}
213
+ tabIndex={null}
214
+ type="button"
215
+ >
216
+ Save setting and sync recommendations
217
+ </button>
218
+ </ButtonBase>
208
219
  </Button>
209
220
  </div>
210
221
  </div>
@@ -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
+ <Memo(Connect(RemediationModal)) />
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
  >