foreman_rh_cloud 4.0.25.1 → 5.0.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) 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/reports_controller.rb +1 -1
  5. data/app/controllers/insights_cloud/api/machine_telemetries_controller.rb +8 -0
  6. data/app/controllers/insights_cloud/hits_controller.rb +1 -1
  7. data/app/models/insights_hit.rb +4 -0
  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_request_forwarder.rb +14 -2
  12. data/config/Gemfile.lock.gh_test +169 -152
  13. data/config/database.yml.example +2 -2
  14. data/config/package-lock.json.plugin +10551 -7500
  15. data/config/routes.rb +1 -1
  16. data/db/migrate/20211027000001_create_task_output.foreman_rh_cloud.rb +18 -0
  17. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +11 -7
  18. data/lib/foreman_inventory_upload/async/generate_report_job.rb +24 -12
  19. data/lib/foreman_inventory_upload/async/progress_output.rb +5 -28
  20. data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +20 -5
  21. data/lib/foreman_inventory_upload/async/shell_process.rb +17 -4
  22. data/lib/foreman_inventory_upload/async/upload_report_job.rb +22 -13
  23. data/lib/foreman_inventory_upload/generators/queries.rb +1 -0
  24. data/lib/foreman_inventory_upload/generators/tags.rb +1 -2
  25. data/lib/foreman_rh_cloud/engine.rb +4 -10
  26. data/lib/foreman_rh_cloud/version.rb +1 -1
  27. data/lib/foreman_rh_cloud.rb +12 -1
  28. data/lib/insights_cloud/async/insights_client_status_aging.rb +4 -0
  29. data/lib/insights_cloud/async/insights_full_sync.rb +4 -0
  30. data/lib/insights_cloud/async/insights_generate_notifications.rb +4 -0
  31. data/lib/insights_cloud/async/insights_resolutions_sync.rb +7 -2
  32. data/lib/insights_cloud/async/insights_rules_sync.rb +10 -2
  33. data/lib/insights_cloud/async/insights_scheduled_sync.rb +11 -7
  34. data/lib/inventory_sync/async/host_result.rb +0 -5
  35. data/lib/inventory_sync/async/inventory_full_sync.rb +18 -9
  36. data/lib/inventory_sync/async/inventory_hosts_sync.rb +6 -6
  37. data/lib/inventory_sync/async/inventory_scheduled_sync.rb +4 -0
  38. data/lib/inventory_sync/async/inventory_self_host_sync.rb +4 -0
  39. data/lib/inventory_sync/async/query_inventory_job.rb +4 -0
  40. data/lib/tasks/rh_cloud_inventory.rake +2 -2
  41. data/package.json +8 -13
  42. data/test/controllers/insights_cloud/api/machine_telemetries_controller_test.rb +16 -39
  43. data/test/controllers/insights_sync/settings_controller_test.rb +2 -2
  44. data/test/controllers/uploads_settings_controller_test.rb +2 -2
  45. data/test/factories/inventory_upload_factories.rb +14 -0
  46. data/test/jobs/insights_full_sync_test.rb +2 -2
  47. data/test/jobs/insights_resolutions_sync_test.rb +11 -2
  48. data/test/jobs/insights_rules_sync_test.rb +2 -2
  49. data/test/jobs/inventory_full_sync_test.rb +31 -5
  50. data/test/jobs/inventory_hosts_sync_test.rb +16 -1
  51. data/test/jobs/inventory_scheduled_sync_test.rb +2 -2
  52. data/test/jobs/inventory_self_host_sync_test.rb +1 -1
  53. data/test/jobs/upload_report_job_test.rb +6 -4
  54. data/test/test_plugin_helper.rb +0 -2
  55. data/test/unit/foreman_rh_cloud_self_host_test.rb +28 -0
  56. data/test/unit/rh_cloud_http_proxy_test.rb +1 -1
  57. data/test/unit/services/foreman_rh_cloud/branch_info_test.rb +1 -1
  58. data/test/unit/services/foreman_rh_cloud/cloud_request_forwarder_test.rb +26 -0
  59. data/test/unit/services/foreman_rh_cloud/template_renderer_helper_test.rb +1 -1
  60. data/test/unit/shell_process_job_test.rb +3 -1
  61. data/test/unit/slice_generator_test.rb +39 -7
  62. data/test/unit/tags_generator_test.rb +20 -20
  63. data/webpack/ForemanInventoryUpload/Components/AccountList/accountList.scss +8 -0
  64. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.scss +17 -4
  65. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageTitle.js +29 -17
  66. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +58 -47
  67. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/PageDescription.js +12 -10
  68. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/PageDescription/__tests__/__snapshots__/PageDescription.test.js.snap +10 -10
  69. data/webpack/ForemanInventoryUpload/SubscriptionsPageExtension/InventoryAutoUpload/__tests__/__snapshots__/InventoryAutoUpload.test.js.snap +1 -1
  70. data/webpack/ForemanRhCloudFills.js +7 -0
  71. data/webpack/InsightsCloudSync/Components/InsightsHeader/index.js +0 -2
  72. data/webpack/InsightsCloudSync/Components/InsightsSettings/insightsSettings.scss +1 -0
  73. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTable.js +22 -6
  74. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableActions.js +23 -16
  75. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableConstants.js +49 -2
  76. data/webpack/InsightsCloudSync/Components/InsightsTable/InsightsTableHelpers.js +31 -14
  77. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +19 -2
  78. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTableActions.test.js.snap +0 -1
  79. data/webpack/InsightsCloudSync/Components/InsightsTable/table.scss +11 -13
  80. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.scss +0 -14
  81. data/webpack/InsightsCloudSync/Components/ToolbarDropdown.js +13 -0
  82. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/InsightsHeader.test.js.snap +0 -1
  83. data/webpack/InsightsCloudSync/Components/__tests__/__snapshots__/NoTokenEmptyState.test.js.snap +24 -13
  84. data/webpack/InsightsCloudSync/InsightsCloudSync.js +2 -0
  85. data/webpack/InsightsCloudSync/InsightsCloudSyncHelpers.js +8 -0
  86. data/webpack/InsightsCloudSync/__snapshots__/InsightsCloudSync.test.js.snap +2 -1
  87. data/webpack/InsightsHostDetailsTab/InsightsTab.scss +4 -0
  88. data/webpack/InsightsHostDetailsTab/NewHostDetailsTab.js +104 -0
  89. data/webpack/__mocks__/foremanReact/components/Head.js +11 -0
  90. data/webpack/common/DropdownToggle.js +24 -0
  91. data/webpack/common/Switcher/HelpLabel.js +1 -1
  92. data/webpack/common/Switcher/__tests__/__snapshots__/HelpLabel.test.js.snap +1 -1
  93. data/webpack/common/Switcher/__tests__/__snapshots__/SwitcherPF4.test.js.snap +1 -0
  94. metadata +11 -3
@@ -4,10 +4,12 @@ import {
4
4
  InsightsLabel,
5
5
  Section,
6
6
  } from '@redhat-cloud-services/frontend-components';
7
+ import { DropdownItem } from '@patternfly/react-core';
7
8
  import { sortable, cellWidth } from '@patternfly/react-table';
8
- import { AnsibeTowerIcon } from '@patternfly/react-icons';
9
+ import { AnsibeTowerIcon, ExternalLinkAltIcon } from '@patternfly/react-icons';
9
10
  import { translate as __ } from 'foremanReact/common/I18n';
10
11
  import { foremanUrl } from '../../../ForemanRhCloudHelpers';
12
+ import DropdownToggle from '../../../common/DropdownToggle';
11
13
 
12
14
  export const totalRiskFormatter = ({ title: totalRisk }) => ({
13
15
  children: (
@@ -28,30 +30,73 @@ export const hasPlaybookFormatter = ({ title: hasPlaybook }) => ({
28
30
  ),
29
31
  });
30
32
 
33
+ export const actionsFormatter = (props, { rowData = {} }) => {
34
+ const { recommendationUrl, accessRHUrl } = rowData;
35
+ const dropdownItems = [];
36
+
37
+ recommendationUrl &&
38
+ dropdownItems.push(
39
+ <DropdownItem key="recommendation-url">
40
+ <a href={recommendationUrl} target="_blank" rel="noopener noreferrer">
41
+ {__('View in Red Hat Insights')} <ExternalLinkAltIcon />
42
+ </a>
43
+ </DropdownItem>
44
+ );
45
+
46
+ accessRHUrl &&
47
+ dropdownItems.push(
48
+ <DropdownItem key="access-url">
49
+ <a href={accessRHUrl} target="_blank" rel="noopener noreferrer">
50
+ {__('Knowledgebase article')} <ExternalLinkAltIcon />
51
+ </a>
52
+ </DropdownItem>
53
+ );
54
+
55
+ return {
56
+ children: <DropdownToggle items={dropdownItems} />,
57
+ };
58
+ };
59
+
31
60
  export const columns = [
32
61
  {
62
+ id: 'hostname',
33
63
  sortKey: 'hostname',
34
64
  title: __('Hostname'),
35
65
  transforms: [cellWidth(20), sortable],
36
66
  },
37
67
  {
68
+ id: 'recommendation',
38
69
  sortKey: 'title',
39
70
  title: __('Recommendation'),
40
71
  transforms: [cellWidth(50), sortable],
41
72
  },
42
73
  {
74
+ id: 'total risk',
43
75
  sortKey: 'total_risk',
44
76
  title: __('Total risk'),
45
77
  transforms: [cellWidth(15), sortable],
46
78
  cellTransforms: [totalRiskFormatter],
47
79
  },
48
80
  {
81
+ id: 'remediate',
49
82
  title: __('Remediate'),
50
- transforms: [cellWidth(15)],
83
+ transforms: [cellWidth(10)],
51
84
  cellTransforms: [hasPlaybookFormatter],
52
85
  },
86
+ {
87
+ id: 'actions',
88
+ title: '',
89
+ transforms: [cellWidth(5)],
90
+ cellTransforms: [actionsFormatter],
91
+ },
53
92
  ];
54
93
 
94
+ export const getColumnsWithoutHostname = () => {
95
+ const nextCols = columns.slice(1);
96
+ nextCols[0].transforms = [cellWidth(70), sortable];
97
+ return nextCols;
98
+ };
99
+
55
100
  export const paginationTitles = {
56
101
  items: __('items'),
57
102
  page: __('page'),
@@ -75,3 +120,5 @@ export const INSIGHTS_SET_SELECTED_IDS = 'INSIGHTS_SET_SELECTED_IDS';
75
120
  export const INSIGHTS_SET_SELECT_ALL_ALERT = 'INSIGHTS_SET_SELECT_ALL_ALERT';
76
121
 
77
122
  export const INSIGHTS_SET_SELECT_ALL = 'INSIGHTS_SET_SELECT_ALL';
123
+
124
+ export const NEW_HOST_PATH = '/new/hosts/';
@@ -1,25 +1,42 @@
1
1
  /* eslint-disable camelcase */
2
- import { columns } from './InsightsTableConstants';
3
-
4
- export const modifySelectedRows = (hits, selectedIds, showSelectAllAlert) => {
2
+ export const modifySelectedRows = (
3
+ hits,
4
+ selectedIds,
5
+ showSelectAllAlert,
6
+ hideHost
7
+ ) => {
5
8
  if (hits.length === 0) return [];
6
9
 
7
10
  return hits
8
11
  .asMutable()
9
- .map(({ id, hostname, title, total_risk, has_playbook }) => {
10
- const disableCheckbox = !has_playbook;
11
- return {
12
- cells: [hostname, title, total_risk, has_playbook],
13
- disableCheckbox,
12
+ .map(
13
+ ({
14
14
  id,
15
- /** The main table checkbox will be seen as selected only if all rows are selected,
16
- * in this case we need to select also the disabled once and hide it with css */
17
- selected: selectedIds[id] || (disableCheckbox && showSelectAllAlert),
18
- };
19
- });
15
+ hostname,
16
+ title,
17
+ total_risk,
18
+ has_playbook,
19
+ results_url,
20
+ solution_url,
21
+ }) => {
22
+ const disableCheckbox = !has_playbook;
23
+ const cells = [hostname, title, total_risk, has_playbook, results_url];
24
+ if (hideHost) cells.shift();
25
+ return {
26
+ cells,
27
+ disableCheckbox,
28
+ id,
29
+ /** The main table checkbox will be seen as selected only if all rows are selected,
30
+ * in this case we need to select also the disabled once and hide it with css */
31
+ selected: selectedIds[id] || (disableCheckbox && showSelectAllAlert),
32
+ recommendationUrl: results_url,
33
+ accessRHUrl: solution_url,
34
+ };
35
+ }
36
+ );
20
37
  };
21
38
 
22
- export const getSortColumnIndex = sortBy => {
39
+ export const getSortColumnIndex = (columns, sortBy) => {
23
40
  let colIndex = 0;
24
41
  columns.forEach((col, index) => {
25
42
  if (col.sortKey === sortBy) {
@@ -17,6 +17,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
17
17
  cells={
18
18
  Array [
19
19
  Object {
20
+ "id": "hostname",
20
21
  "sortKey": "hostname",
21
22
  "title": "Hostname",
22
23
  "transforms": Array [
@@ -25,6 +26,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
25
26
  ],
26
27
  },
27
28
  Object {
29
+ "id": "recommendation",
28
30
  "sortKey": "title",
29
31
  "title": "Recommendation",
30
32
  "transforms": Array [
@@ -36,6 +38,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
36
38
  "cellTransforms": Array [
37
39
  [Function],
38
40
  ],
41
+ "id": "total risk",
39
42
  "sortKey": "total_risk",
40
43
  "title": "Total risk",
41
44
  "transforms": Array [
@@ -47,20 +50,34 @@ exports[`InsightsTable rendering render with Props 1`] = `
47
50
  "cellTransforms": Array [
48
51
  [Function],
49
52
  ],
53
+ "id": "remediate",
50
54
  "title": "Remediate",
51
55
  "transforms": Array [
52
56
  [Function],
53
57
  ],
54
58
  },
59
+ Object {
60
+ "cellTransforms": Array [
61
+ [Function],
62
+ ],
63
+ "id": "actions",
64
+ "title": "",
65
+ "transforms": Array [
66
+ [Function],
67
+ ],
68
+ },
55
69
  ]
56
70
  }
57
- className="recommendations-table"
71
+ className="rh-cloud-recommendations-table"
58
72
  contentId="expanded-content"
59
73
  dropdownDirection="down"
60
74
  dropdownPosition="right"
61
75
  expandId="expandable-toggle"
62
76
  gridBreakPoint="grid-md"
77
+ isHeaderSelectDisabled={false}
78
+ isNested={false}
63
79
  isStickyHeader={false}
80
+ isTreeTable={false}
64
81
  onSelect={[Function]}
65
82
  onSort={[Function]}
66
83
  ouiaSafe={true}
@@ -77,7 +94,7 @@ exports[`InsightsTable rendering render with Props 1`] = `
77
94
  variant="compact"
78
95
  >
79
96
  <TableHeader />
80
- <Component />
97
+ <TableBody />
81
98
  </Table>
82
99
  <TableEmptyState
83
100
  error={null}
@@ -31,7 +31,6 @@ Array [
31
31
  "payload": Object {
32
32
  "args": Array [
33
33
  Object {
34
- "pathname": "/foreman_rh_cloud/insights_cloud",
35
34
  "search": "?page=2&per_page=7&search=&sort_by=&sort_order=&select_all=true",
36
35
  },
37
36
  ],
@@ -1,21 +1,19 @@
1
1
  @import '~@redhat-cloud-services/frontend-components/index.css';
2
2
 
3
- .rh-cloud-insights {
4
- .recommendations-table {
5
- .pf-c-table__check {
6
- input:disabled {
7
- display: none;
8
- }
3
+ .rh-cloud-recommendations-table {
4
+ .pf-c-table__check {
5
+ input:disabled {
6
+ display: none;
9
7
  }
8
+ }
10
9
 
11
- .td-insights-remediate-playbook {
12
- svg {
13
- margin-right: 5px;
14
- }
10
+ .td-insights-remediate-playbook {
11
+ svg {
12
+ margin-right: 5px;
15
13
  }
14
+ }
16
15
 
17
- .td-insights-remediate-manual {
18
- padding-left: 18px;
19
- }
16
+ .td-insights-remediate-manual {
17
+ padding-left: 18px;
20
18
  }
21
19
  }
@@ -6,18 +6,4 @@
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
- }
23
9
  }
@@ -2,6 +2,8 @@ import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import { Dropdown, DropdownItem, KebabToggle } from '@patternfly/react-core';
5
+ import { ExternalLinkAltIcon } from '@patternfly/react-icons';
6
+ import { redHatAdvisorSystems } from '../InsightsCloudSyncHelpers';
5
7
 
6
8
  const ToolbarDropdown = ({ onRecommendationSync }) => {
7
9
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);
@@ -12,6 +14,17 @@ const ToolbarDropdown = ({ onRecommendationSync }) => {
12
14
  >
13
15
  {__('Sync recommendations')}
14
16
  </DropdownItem>,
17
+ <DropdownItem key="cloud-advisor-systems-link">
18
+ <a
19
+ href={redHatAdvisorSystems()}
20
+ target="_blank"
21
+ rel="noopener noreferrer"
22
+ >
23
+ {__('View in Red Hat Insights')}
24
+ {' '}
25
+ <ExternalLinkAltIcon />
26
+ </a>
27
+ </DropdownItem>,
15
28
  ];
16
29
  return (
17
30
  <Dropdown
@@ -4,7 +4,6 @@ exports[`InsightsHeader render 1`] = `
4
4
  <div
5
5
  className="insights-header"
6
6
  >
7
- <Connect(InsightsSettings) />
8
7
  <Text
9
8
  component="p"
10
9
  >
@@ -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>
@@ -12,6 +12,7 @@ import {
12
12
  import './InsightsCloudSync.scss';
13
13
  import Pagination from './Components/InsightsTable/Pagination';
14
14
  import ToolbarDropdown from './Components/ToolbarDropdown';
15
+ import InsightsSettings from './Components/InsightsSettings';
15
16
 
16
17
  const InsightsCloudSync = ({
17
18
  syncInsights,
@@ -42,6 +43,7 @@ const InsightsCloudSync = ({
42
43
 
43
44
  return (
44
45
  <div className="rh-cloud-insights">
46
+ <InsightsSettings />
45
47
  <PageLayout
46
48
  searchable
47
49
  searchProps={INSIGHTS_SEARCH_PROPS}
@@ -8,3 +8,11 @@ export const cloudTokenSettingUrl = () => {
8
8
  settingsUrl.setSearch({ search: 'name = rh_cloud_token' });
9
9
  return settingsUrl.toString();
10
10
  };
11
+
12
+ export const redHatConsole = path => `https://console.redhat.com/${path || ''}`;
13
+ export const redHatInsights = path => redHatConsole(`insights/${path || ''}`);
14
+ export const redHatInventory = path =>
15
+ redHatInsights(`inventory/${path || ''}`);
16
+ export const redHatAdvisor = path => redHatInsights(`advisor/${path || ''}`);
17
+ export const redHatAdvisorSystems = path =>
18
+ redHatAdvisor(`systems/${path || ''}`);
@@ -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"
@@ -31,7 +32,7 @@ exports[`InsightsCloudSync render 1`] = `
31
32
  <span
32
33
  className="insights-toolbar-buttons"
33
34
  >
34
- <UNDEFINED />
35
+ <Memo(Connect(RemediationModal)) />
35
36
  <ToolbarDropdown
36
37
  onRecommendationSync={[Function]}
37
38
  />
@@ -84,3 +84,7 @@
84
84
  }
85
85
  }
86
86
  }
87
+
88
+ #new_host_details_insights_tab {
89
+ padding: 24px;
90
+ }
@@ -0,0 +1,104 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useDispatch, useSelector } from 'react-redux';
4
+ import SearchBar from 'foremanReact/components/SearchBar';
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+ import {
7
+ Grid,
8
+ GridItem,
9
+ Dropdown,
10
+ DropdownItem,
11
+ KebabToggle,
12
+ } from '@patternfly/react-core';
13
+ import { ExternalLinkAltIcon } from '@patternfly/react-icons';
14
+ import InsightsTable from '../InsightsCloudSync/Components/InsightsTable';
15
+ import RemediationModal from '../InsightsCloudSync/Components/RemediationModal';
16
+ import Pagination from '../InsightsCloudSync/Components/InsightsTable/Pagination';
17
+ import { INSIGHTS_SEARCH_PROPS } from '../InsightsCloudSync/InsightsCloudSyncConstants';
18
+ import { fetchInsights } from '../InsightsCloudSync/Components/InsightsTable/InsightsTableActions';
19
+ import {
20
+ selectSearch,
21
+ selectHits,
22
+ } from '../InsightsCloudSync/Components/InsightsTable/InsightsTableSelectors';
23
+ import './InsightsTab.scss';
24
+ import { redHatAdvisorSystems } from '../InsightsCloudSync/InsightsCloudSyncHelpers';
25
+
26
+ const NewHostDetailsTab = ({ hostName, router }) => {
27
+ const dispatch = useDispatch();
28
+ const query = useSelector(selectSearch);
29
+ const hits = useSelector(selectHits);
30
+
31
+ useEffect(() => () => router.replace({ search: null }), [router]);
32
+
33
+ const onSearch = q => dispatch(fetchInsights({ query: q, page: 1 }));
34
+
35
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
36
+ const onSatInsightsClick = () =>
37
+ router.push({ pathname: '/foreman_rh_cloud/insights_cloud' });
38
+
39
+ const dropdownItems = [
40
+ <DropdownItem key="insights-link">
41
+ <a onClick={onSatInsightsClick}>{__('Go to Satellite Insights page')}</a>
42
+ </DropdownItem>,
43
+ ];
44
+
45
+ if (hits.length) {
46
+ const { host_uuid: uuid } = hits[0];
47
+ dropdownItems.push(
48
+ <DropdownItem key="insights-advisor-link">
49
+ <a
50
+ href={redHatAdvisorSystems(uuid)}
51
+ target="_blank"
52
+ rel="noopener noreferrer"
53
+ >
54
+ {__('View in Red Hat Insights')}
55
+ {' '}
56
+ <ExternalLinkAltIcon />
57
+ </a>
58
+ </DropdownItem>
59
+ );
60
+ }
61
+
62
+ return (
63
+ <Grid id="new_host_details_insights_tab" hasGutter>
64
+ <GridItem span={5}>
65
+ <SearchBar
66
+ data={INSIGHTS_SEARCH_PROPS}
67
+ onSearch={onSearch}
68
+ initialQuery={query}
69
+ />
70
+ </GridItem>
71
+ <GridItem span={4}>
72
+ <RemediationModal />
73
+ <Dropdown
74
+ className="insights-dropdown"
75
+ onSelect={() => setIsDropdownOpen(false)}
76
+ toggle={
77
+ <KebabToggle onToggle={isOpen => setIsDropdownOpen(isOpen)} />
78
+ }
79
+ isOpen={isDropdownOpen}
80
+ isPlain
81
+ dropdownItems={dropdownItems}
82
+ />
83
+ </GridItem>
84
+ <GridItem span={3}>
85
+ <Pagination variant="top" isCompact />
86
+ </GridItem>
87
+ <GridItem>
88
+ <InsightsTable hideHost hostname={hostName} />
89
+ </GridItem>
90
+ </Grid>
91
+ );
92
+ };
93
+
94
+ NewHostDetailsTab.propTypes = {
95
+ hostName: PropTypes.string,
96
+ router: PropTypes.object,
97
+ };
98
+
99
+ NewHostDetailsTab.defaultProps = {
100
+ hostName: '',
101
+ router: {},
102
+ };
103
+
104
+ export default NewHostDetailsTab;
@@ -0,0 +1,11 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import { Helmet } from 'react-helmet';
4
+
5
+ const Head = ({ children }) => <Helmet>{children}</Helmet>;
6
+
7
+ Head.propTypes = {
8
+ children: PropTypes.node.isRequired,
9
+ };
10
+
11
+ export default Head;
@@ -0,0 +1,24 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Dropdown, KebabToggle } from '@patternfly/react-core';
4
+
5
+ const DropdownToggle = ({ items, ...props }) => {
6
+ const [isOpen, setOpen] = useState(false);
7
+ return (
8
+ <Dropdown
9
+ onSelect={() => setOpen(false)}
10
+ toggle={<KebabToggle onToggle={value => setOpen(value)} />}
11
+ isOpen={isOpen}
12
+ isPlain
13
+ dropdownItems={items}
14
+ position="right"
15
+ {...props}
16
+ />
17
+ );
18
+ };
19
+
20
+ DropdownToggle.propTypes = {
21
+ items: PropTypes.array.isRequired,
22
+ };
23
+
24
+ export default DropdownToggle;
@@ -11,7 +11,7 @@ export const HelpLabel = ({ text, id, className }) => {
11
11
  onClick={e => e.preventDefault()}
12
12
  className={`pf-c-form__group-label-help ${className}`}
13
13
  >
14
- <HelpIcon noVerticalAlign />
14
+ <HelpIcon />
15
15
  </button>
16
16
  </Popover>
17
17
  );
@@ -12,7 +12,7 @@ exports[`InsightsCloudSync helpers should return insights cloud Url 1`] = `
12
12
  >
13
13
  <HelpIcon
14
14
  color="currentColor"
15
- noVerticalAlign={true}
15
+ noVerticalAlign={false}
16
16
  size="sm"
17
17
  />
18
18
  </button>
@@ -7,6 +7,7 @@ exports[`InsightsCloudSync helpers should return insights cloud Url 1`] = `
7
7
  id="rh-cloud-switcher-some-id"
8
8
  isChecked={true}
9
9
  isDisabled={false}
10
+ isReversed={false}
10
11
  label={
11
12
  <div>
12
13
  some-label