foreman_rh_cloud 13.0.8 → 13.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/inventory_upload/report_actions.rb +8 -1
  3. data/app/controllers/foreman_inventory_upload/accounts_controller.rb +82 -7
  4. data/app/controllers/foreman_inventory_upload/api/tasks_controller.rb +110 -0
  5. data/app/controllers/foreman_inventory_upload/reports_controller.rb +41 -17
  6. data/app/controllers/foreman_inventory_upload/uploads_controller.rb +0 -9
  7. data/config/routes.rb +4 -2
  8. data/db/migrate/20251209163012_drop_task_output_tables.foreman_rh_cloud.rb +24 -0
  9. data/lib/foreman_inventory_upload/async/generate_all_reports_job.rb +1 -1
  10. data/lib/foreman_inventory_upload/async/host_inventory_report_job.rb +39 -0
  11. data/lib/foreman_inventory_upload/async/queue_for_upload_job.rb +1 -23
  12. data/lib/foreman_inventory_upload/async/upload_report_direct_job.rb +171 -0
  13. data/lib/foreman_inventory_upload.rb +0 -4
  14. data/lib/foreman_rh_cloud/plugin.rb +1 -0
  15. data/lib/foreman_rh_cloud/version.rb +1 -1
  16. data/lib/inventory_sync/async/inventory_hosts_sync.rb +0 -2
  17. data/lib/tasks/rh_cloud_inventory.rake +4 -2
  18. data/package.json +1 -1
  19. data/test/controllers/accounts_controller_test.rb +10 -11
  20. data/test/controllers/insights_cloud/api/cloud_request_controller_test.rb +1 -2
  21. data/test/jobs/host_inventory_report_job_test.rb +161 -97
  22. data/test/jobs/queue_for_upload_job_test.rb +1 -12
  23. data/test/jobs/single_host_report_job_test.rb +36 -54
  24. data/test/jobs/upload_report_direct_job_test.rb +399 -0
  25. data/test/unit/rh_cloud_permissions_test.rb +2 -0
  26. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.fixtures.js +6 -6
  27. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountList.js +49 -34
  28. data/webpack/ForemanInventoryUpload/Components/AccountList/AccountListActions.js +2 -2
  29. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.fixtures.js +4 -5
  30. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/ListItem.js +15 -7
  31. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItem/__tests__/__snapshots__/ListItem.test.js.snap +11 -11
  32. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/ListItemStatus.fixtures.js +2 -2
  33. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/ListItemStatus.js +10 -14
  34. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/ListItemStatusHelper.js +9 -4
  35. data/webpack/ForemanInventoryUpload/Components/AccountList/Components/ListItemStatus/__tests__/__snapshots__/ListItemStatus.test.js.snap +4 -4
  36. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountList.test.js.snap +15 -9
  37. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListActions.test.js.snap +7 -7
  38. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListReducer.test.js.snap +6 -6
  39. data/webpack/ForemanInventoryUpload/Components/AccountList/__tests__/__snapshots__/AccountListSelectors.test.js.snap +12 -12
  40. data/webpack/ForemanInventoryUpload/Components/Dashboard/Dashboard.js +37 -130
  41. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/Dashboard.test.js +60 -17
  42. data/webpack/ForemanInventoryUpload/Components/Dashboard/index.js +1 -34
  43. data/webpack/ForemanInventoryUpload/Components/InventoryFilter/__tests__/__snapshots__/integration.test.js.snap +0 -1
  44. data/webpack/ForemanInventoryUpload/Components/NavContainer/NavContainer.js +1 -26
  45. data/webpack/ForemanInventoryUpload/Components/PageHeader/PageHeader.js +24 -17
  46. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/PageHeader.test.js +178 -8
  47. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageTitle.test.js.snap +2 -2
  48. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/ToolbarButtons.js +3 -1
  49. data/webpack/ForemanInventoryUpload/Components/PageHeader/components/ToolbarButtons/__tests__/ToolbarButtons.test.js +69 -51
  50. data/webpack/ForemanInventoryUpload/Components/TabHeader/TabHeader.js +22 -9
  51. data/webpack/ForemanInventoryUpload/Components/TabHeader/__tests__/TabHeader.test.js +67 -4
  52. data/webpack/ForemanInventoryUpload/Components/TaskHistory/TaskHistory.js +140 -0
  53. data/webpack/ForemanInventoryUpload/Components/TaskHistory/index.js +1 -0
  54. data/webpack/ForemanInventoryUpload/Components/TaskHistory/taskHistory.scss +40 -0
  55. data/webpack/ForemanInventoryUpload/Components/TaskProgress/TaskProgress.js +340 -0
  56. data/webpack/ForemanInventoryUpload/Components/TaskProgress/index.js +1 -0
  57. data/webpack/ForemanInventoryUpload/Components/TaskProgress/taskProgress.scss +8 -0
  58. data/webpack/ForemanInventoryUpload/ForemanInventoryHelpers.js +2 -2
  59. data/webpack/ForemanInventoryUpload/ForemanInventoryUploadReducers.js +0 -2
  60. data/webpack/ForemanInventoryUpload/__tests__/__snapshots__/ForemanInventoryHelpers.test.js.snap +1 -1
  61. data/webpack/ForemanRhCloudPages.js +0 -1
  62. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/InsightsTable.test.js +11 -19
  63. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationHelpers.js +1 -2
  64. data/webpack/InsightsCloudSync/Components/RemediationModal/RemediationModal.js +2 -4
  65. data/webpack/InsightsVulnerabilityHostIndexExtensions/__tests__/CVECountCell.test.js +77 -22
  66. data/webpack/__mocks__/foremanReact/components/common/dates/RelativeDateTime.js +14 -0
  67. data/webpack/__tests__/ForemanRhCloudHelpers.test.js +5 -1
  68. metadata +13 -68
  69. data/app/models/task_output_line.rb +0 -2
  70. data/app/models/task_output_status.rb +0 -2
  71. data/lib/foreman_inventory_upload/async/generate_report_job.rb +0 -61
  72. data/lib/foreman_inventory_upload/async/progress_output.rb +0 -38
  73. data/lib/foreman_inventory_upload/async/shell_process.rb +0 -77
  74. data/lib/foreman_inventory_upload/async/upload_report_job.rb +0 -97
  75. data/lib/foreman_inventory_upload/scripts/uploader.sh.erb +0 -55
  76. data/test/controllers/reports_controller_test.rb +0 -21
  77. data/test/controllers/uploads_controller_test.rb +0 -21
  78. data/test/jobs/generate_report_job_test.rb +0 -146
  79. data/test/jobs/upload_report_job_test.rb +0 -38
  80. data/test/unit/shell_process_job_test.rb +0 -29
  81. data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardActions.js +0 -88
  82. data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardConstants.js +0 -9
  83. data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardReducer.js +0 -68
  84. data/webpack/ForemanInventoryUpload/Components/Dashboard/DashboardSelectors.js +0 -17
  85. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardActions.test.js +0 -51
  86. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardIntegration.test.js +0 -17
  87. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardReducer.test.js +0 -64
  88. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/DashboardSelectors.test.js +0 -46
  89. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/Dashboard.test.js.snap +0 -36
  90. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/DashboardActions.test.js.snap +0 -76
  91. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/DashboardReducer.test.js.snap +0 -44
  92. data/webpack/ForemanInventoryUpload/Components/Dashboard/__tests__/__snapshots__/DashboardSelectors.test.js.snap +0 -42
  93. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModal.fixtures.js +0 -0
  94. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModal.js +0 -55
  95. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/FullScreenModalHelper.js +0 -0
  96. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/__tests__/FullScreenModal.test.js +0 -13
  97. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/__tests__/__snapshots__/FullScreenModal.test.js.snap +0 -65
  98. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/fullScreenModal.scss +0 -20
  99. data/webpack/ForemanInventoryUpload/Components/FullScreenModal/index.js +0 -1
  100. data/webpack/ForemanInventoryUpload/Components/PageHeader/__tests__/__snapshots__/PageHeader.test.js.snap +0 -36
  101. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.fixtures.js +0 -18
  102. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerate.js +0 -65
  103. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/ReportGenerateHelper.js +0 -0
  104. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/__tests__/ReportGenerate.test.js +0 -14
  105. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/__tests__/__snapshots__/ReportGenerate.test.js.snap +0 -47
  106. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/index.js +0 -1
  107. data/webpack/ForemanInventoryUpload/Components/ReportGenerate/reportGenerate.scss +0 -0
  108. data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUpload.fixtures.js +0 -18
  109. data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUpload.js +0 -46
  110. data/webpack/ForemanInventoryUpload/Components/ReportUpload/ReportUploadHelper.js +0 -0
  111. data/webpack/ForemanInventoryUpload/Components/ReportUpload/__tests__/ReportUpload.test.js +0 -14
  112. data/webpack/ForemanInventoryUpload/Components/ReportUpload/__tests__/__snapshots__/ReportUpload.test.js.snap +0 -47
  113. data/webpack/ForemanInventoryUpload/Components/ReportUpload/index.js +0 -1
  114. data/webpack/ForemanInventoryUpload/Components/ReportUpload/reportUpload.scss +0 -0
  115. data/webpack/ForemanInventoryUpload/Components/TabBody/TabBody.fixtures.js +0 -0
  116. data/webpack/ForemanInventoryUpload/Components/TabBody/TabBody.js +0 -31
  117. data/webpack/ForemanInventoryUpload/Components/TabBody/TabBodyHelper.js +0 -0
  118. data/webpack/ForemanInventoryUpload/Components/TabBody/__tests__/TabBody.test.js +0 -13
  119. data/webpack/ForemanInventoryUpload/Components/TabBody/__tests__/__snapshots__/TabBody.test.js.snap +0 -19
  120. data/webpack/ForemanInventoryUpload/Components/TabBody/index.js +0 -1
  121. data/webpack/ForemanInventoryUpload/Components/TabBody/tabBody.scss +0 -5
  122. data/webpack/ForemanInventoryUpload/Components/Terminal/Terminal.fixtures.js +0 -10
  123. data/webpack/ForemanInventoryUpload/Components/Terminal/Terminal.js +0 -110
  124. data/webpack/ForemanInventoryUpload/Components/Terminal/TerminalHelper.js +0 -6
  125. data/webpack/ForemanInventoryUpload/Components/Terminal/__tests__/Terminal.test.js +0 -34
  126. data/webpack/ForemanInventoryUpload/Components/Terminal/__tests__/__snapshots__/Terminal.test.js.snap +0 -98
  127. data/webpack/ForemanInventoryUpload/Components/Terminal/index.js +0 -1
  128. data/webpack/ForemanInventoryUpload/Components/Terminal/terminal.scss +0 -32
  129. data/webpack/InsightsCloudSync/Components/InsightsTable/__tests__/__snapshots__/InsightsTable.test.js.snap +0 -112
  130. data/webpack/__mocks__/foremanReact/common/hooks/API/APIHooks.js +0 -3
@@ -5,21 +5,17 @@ import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import { getStatusIconByRegex } from './ListItemStatusHelper';
6
6
 
7
7
  const ListItemStatus = ({ account }) => {
8
- const generatingStatusIcon = getStatusIconByRegex(
9
- account.generate_report_status
10
- );
11
- const uploadingStatusIcon = getStatusIconByRegex(
12
- account.upload_report_status
13
- );
8
+ const generatedStatusIcon = getStatusIconByRegex(account.generated_status);
9
+ const uploadedStatusIcon = getStatusIconByRegex(account.uploaded_status);
14
10
  return (
15
11
  <Grid hasGutter className="status">
16
12
  <GridItem span={6} className="item">
17
- <p>{__('Generating')}</p>
18
- {generatingStatusIcon}
13
+ <p>{__('Generated')}</p>
14
+ {generatedStatusIcon}
19
15
  </GridItem>
20
16
  <GridItem span={6} className="item">
21
- <p>{__('Uploading')}</p>
22
- {uploadingStatusIcon}
17
+ <p>{__('Uploaded')}</p>
18
+ {uploadedStatusIcon}
23
19
  </GridItem>
24
20
  </Grid>
25
21
  );
@@ -27,15 +23,15 @@ const ListItemStatus = ({ account }) => {
27
23
 
28
24
  ListItemStatus.propTypes = {
29
25
  account: PropTypes.shape({
30
- generate_report_status: PropTypes.string,
31
- upload_report_status: PropTypes.string,
26
+ generated_status: PropTypes.string,
27
+ uploaded_status: PropTypes.string,
32
28
  }),
33
29
  };
34
30
 
35
31
  ListItemStatus.defaultProps = {
36
32
  account: {
37
- generate_report_status: 'unknown',
38
- uploupload_report_statusading: 'unknown',
33
+ generated_status: 'unknown',
34
+ uploaded_status: 'unknown',
39
35
  },
40
36
  };
41
37
 
@@ -14,17 +14,22 @@ export const getStatusIconByRegex = status => {
14
14
  return STATUS_ICONS.unknown;
15
15
  }
16
16
 
17
- const statusCopy = status.toLowerCase();
18
- if (statusCopy.indexOf('exit 0') !== -1) {
17
+ const statusLower = status.toLowerCase();
18
+
19
+ // Success states
20
+ if (statusLower === 'success') {
19
21
  return STATUS_ICONS.success;
20
22
  }
21
23
 
24
+ // Running states
22
25
  if (
23
- statusCopy.indexOf('running') !== -1 ||
24
- statusCopy.indexOf('restarting') !== -1
26
+ statusLower === 'running' ||
27
+ statusLower === 'pending' ||
28
+ statusLower === 'scheduled'
25
29
  ) {
26
30
  return STATUS_ICONS.running;
27
31
  }
28
32
 
33
+ // Failure states (error, warning, or anything else)
29
34
  return STATUS_ICONS.failure;
30
35
  };
@@ -10,7 +10,7 @@ exports[`ListItemStatus rendering render with Props 1`] = `
10
10
  span={6}
11
11
  >
12
12
  <p>
13
- Generating
13
+ Generated
14
14
  </p>
15
15
  <CheckIcon />
16
16
  </GridItem>
@@ -19,7 +19,7 @@ exports[`ListItemStatus rendering render with Props 1`] = `
19
19
  span={6}
20
20
  >
21
21
  <p>
22
- Uploading
22
+ Uploaded
23
23
  </p>
24
24
  <Spinner
25
25
  size="sm"
@@ -38,7 +38,7 @@ exports[`ListItemStatus rendering render without Props 1`] = `
38
38
  span={6}
39
39
  >
40
40
  <p>
41
- Generating
41
+ Generated
42
42
  </p>
43
43
  <span>
44
44
  --
@@ -49,7 +49,7 @@ exports[`ListItemStatus rendering render without Props 1`] = `
49
49
  span={6}
50
50
  >
51
51
  <p>
52
- Uploading
52
+ Uploaded
53
53
  </p>
54
54
  <span>
55
55
  --
@@ -7,35 +7,41 @@ exports[`AccountList rendering render with props 1`] = `
7
7
  <ListItem
8
8
  account={
9
9
  Object {
10
- "generate_report_status": "running",
10
+ "generated_status": "running",
11
11
  "id": 1,
12
- "upload_report_status": "running",
12
+ "uploaded_status": "running",
13
13
  }
14
14
  }
15
- key="0"
15
+ defaultExpanded={true}
16
+ key="Account1"
16
17
  label="Account1"
18
+ onTaskStart={[Function]}
17
19
  />
18
20
  <ListItem
19
21
  account={
20
22
  Object {
21
- "generate_report_status": "failure",
23
+ "generated_status": "failure",
22
24
  "id": 2,
23
- "upload_report_status": "unknown",
25
+ "uploaded_status": "unknown",
24
26
  }
25
27
  }
26
- key="1"
28
+ defaultExpanded={false}
29
+ key="Account2"
27
30
  label="Account2"
31
+ onTaskStart={[Function]}
28
32
  />
29
33
  <ListItem
30
34
  account={
31
35
  Object {
32
- "generate_report_status": "running",
36
+ "generated_status": "running",
33
37
  "id": 3,
34
- "upload_report_status": "success",
38
+ "uploaded_status": "success",
35
39
  }
36
40
  }
37
- key="2"
41
+ defaultExpanded={false}
42
+ key="Account3"
38
43
  label="Account3"
44
+ onTaskStart={[Function]}
39
45
  />
40
46
  </Accordion>
41
47
  `;
@@ -13,19 +13,19 @@ Array [
13
13
  },
14
14
  "accounts": Object {
15
15
  "Account1": Object {
16
- "generate_report_status": "running",
16
+ "generated_status": "running",
17
17
  "id": 1,
18
- "upload_report_status": "running",
18
+ "uploaded_status": "running",
19
19
  },
20
20
  "Account2": Object {
21
- "generate_report_status": "failure",
21
+ "generated_status": "failure",
22
22
  "id": 2,
23
- "upload_report_status": "unknown",
23
+ "uploaded_status": "unknown",
24
24
  },
25
25
  "Account3": Object {
26
- "generate_report_status": "running",
26
+ "generated_status": "running",
27
27
  "id": 3,
28
- "upload_report_status": "success",
28
+ "uploaded_status": "success",
29
29
  },
30
30
  },
31
31
  },
@@ -58,7 +58,7 @@ Array [
58
58
  Object {
59
59
  "payload": Object {
60
60
  "accountID": "some-account-ID",
61
- "processStatusName": "generate_report_status",
61
+ "processStatusName": "generated_status",
62
62
  },
63
63
  "type": "INVENTORY_PROCESS_RESTART",
64
64
  },
@@ -10,19 +10,19 @@ Object {
10
10
  },
11
11
  "accounts": Object {
12
12
  "Account1": Object {
13
- "generate_report_status": "running",
13
+ "generated_status": "running",
14
14
  "id": 1,
15
- "upload_report_status": "running",
15
+ "uploaded_status": "running",
16
16
  },
17
17
  "Account2": Object {
18
- "generate_report_status": "failure",
18
+ "generated_status": "failure",
19
19
  "id": 2,
20
- "upload_report_status": "unknown",
20
+ "uploaded_status": "unknown",
21
21
  },
22
22
  "Account3": Object {
23
- "generate_report_status": "running",
23
+ "generated_status": "running",
24
24
  "id": 3,
25
- "upload_report_status": "success",
25
+ "uploaded_status": "success",
26
26
  },
27
27
  },
28
28
  "error": null,
@@ -3,19 +3,19 @@
3
3
  exports[`AccountList selectors should return AccountList accounts 1`] = `
4
4
  Object {
5
5
  "Account1": Object {
6
- "generate_report_status": "running",
6
+ "generated_status": "running",
7
7
  "id": 1,
8
- "upload_report_status": "running",
8
+ "uploaded_status": "running",
9
9
  },
10
10
  "Account2": Object {
11
- "generate_report_status": "failure",
11
+ "generated_status": "failure",
12
12
  "id": 2,
13
- "upload_report_status": "unknown",
13
+ "uploaded_status": "unknown",
14
14
  },
15
15
  "Account3": Object {
16
- "generate_report_status": "running",
16
+ "generated_status": "running",
17
17
  "id": 3,
18
- "upload_report_status": "success",
18
+ "uploaded_status": "success",
19
19
  },
20
20
  }
21
21
  `;
@@ -26,19 +26,19 @@ exports[`AccountList selectors should return AccountsList 1`] = `
26
26
  Object {
27
27
  "accounts": Object {
28
28
  "Account1": Object {
29
- "generate_report_status": "running",
29
+ "generated_status": "running",
30
30
  "id": 1,
31
- "upload_report_status": "running",
31
+ "uploaded_status": "running",
32
32
  },
33
33
  "Account2": Object {
34
- "generate_report_status": "failure",
34
+ "generated_status": "failure",
35
35
  "id": 2,
36
- "upload_report_status": "unknown",
36
+ "uploaded_status": "unknown",
37
37
  },
38
38
  "Account3": Object {
39
- "generate_report_status": "running",
39
+ "generated_status": "running",
40
40
  "id": 3,
41
- "upload_report_status": "success",
41
+ "uploaded_status": "success",
42
42
  },
43
43
  },
44
44
  "pollingProcessID": 0,
@@ -1,149 +1,56 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { noop } from 'foremanReact/common/helpers';
4
3
  import { translate as __ } from 'foremanReact/common/I18n';
5
- import ReportGenerate from '../ReportGenerate';
6
- import ReportUpload from '../ReportUpload';
7
- import NavContainer from '../NavContainer';
4
+ import TaskProgress from '../TaskProgress';
8
5
  import './dashboard.scss';
9
6
 
10
- class Dashboard extends React.Component {
11
- componentDidMount() {
12
- const { startPolling, fetchLogs, accountID } = this.props;
13
- fetchLogs(accountID);
14
- const pollingProcessID = setInterval(() => fetchLogs(accountID), 5000);
15
- startPolling(accountID, pollingProcessID);
16
- }
17
-
18
- componentWillUnmount() {
19
- const { stopPolling, pollingProcessID, accountID } = this.props;
20
- stopPolling(accountID, pollingProcessID);
21
- }
22
-
23
- handleDownload = () => {
24
- const { downloadReports, accountID } = this.props;
25
- downloadReports(accountID);
26
- };
27
-
28
- handleRestart = () => {
29
- const { restartProcess, accountID, activeTab } = this.props;
30
- restartProcess(accountID, activeTab);
31
- };
32
-
33
- handleTabChange = async tabName => {
34
- const { setActiveTab, accountID, fetchLogs } = this.props;
35
- await setActiveTab(accountID, tabName);
36
- fetchLogs(accountID);
37
- };
38
-
39
- handleToggleFullScreen = () => {
40
- const { toggleFullScreen, accountID } = this.props;
41
- toggleFullScreen(accountID);
42
- };
43
-
44
- render() {
45
- const {
46
- uploading,
47
- generating,
48
- account,
49
- showFullScreen,
50
- activeTab,
51
- } = this.props;
52
- const downloadButtonDisabled = () => account.report_file_paths.length === 0;
7
+ const Dashboard = ({ account, onTaskStart }) => {
8
+ // Defensive handling for missing or malformed account data
9
+ if (!account) {
53
10
  return (
54
- <NavContainer
55
- items={[
56
- {
57
- icon: 'database',
58
- name: __('Generating'),
59
- component: ReportGenerate,
60
- props: {
61
- ...generating,
62
- restartProcess: this.handleRestart,
63
- exitCode: account.generate_report_status,
64
- downloadReports: this.handleDownload,
65
- downloadButtonDisabled,
66
- toggleFullScreen: this.handleToggleFullScreen,
67
- },
68
- onClick: () => this.handleTabChange('generating'),
69
- },
70
- {
71
- icon: 'cloud-upload',
72
- name: __('Uploading'),
73
- component: ReportUpload,
74
- props: {
75
- ...uploading,
76
- exitCode: account.upload_report_status,
77
- toggleFullScreen: this.handleToggleFullScreen,
78
- },
79
- onClick: () => this.handleTabChange('uploading'),
80
- },
81
- ]}
82
- toggleFullScreen={this.handleToggleFullScreen}
83
- showFullScreen={showFullScreen}
84
- terminalProps={this.props[activeTab]}
11
+ <TaskProgress
12
+ task={null}
13
+ title={__('Report Generation')}
14
+ emptyMessage={__('No account data available.')}
15
+ organizationId={null}
16
+ taskType="generate"
17
+ onTaskStart={onTaskStart}
85
18
  />
86
19
  );
87
20
  }
88
- }
21
+
22
+ return (
23
+ <TaskProgress
24
+ task={account.generate_task || null}
25
+ title={__('Report Generation')}
26
+ emptyMessage={__('No report generation tasks have been run yet.')}
27
+ organizationId={account.id || null}
28
+ taskType="generate"
29
+ onTaskStart={onTaskStart}
30
+ />
31
+ );
32
+ };
89
33
 
90
34
  Dashboard.propTypes = {
91
- accountID: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
92
- .isRequired,
93
- startPolling: PropTypes.func,
94
- fetchLogs: PropTypes.func,
95
- stopPolling: PropTypes.func,
96
- setActiveTab: PropTypes.func,
97
- uploading: PropTypes.shape({
98
- exitCode: PropTypes.string,
99
- logs: PropTypes.oneOfType([
100
- PropTypes.arrayOf(PropTypes.string),
101
- PropTypes.string,
102
- ]),
103
- completed: PropTypes.number,
104
- files: PropTypes.arrayOf(PropTypes.string),
105
- error: PropTypes.string,
106
- }),
107
- generating: PropTypes.shape({
108
- exitCode: PropTypes.string,
109
- logs: PropTypes.oneOfType([
110
- PropTypes.arrayOf(PropTypes.string),
111
- PropTypes.string,
112
- ]),
113
- completed: PropTypes.number,
114
- error: PropTypes.string,
115
- }),
116
- restartProcess: PropTypes.func,
117
- downloadReports: PropTypes.func,
118
- pollingProcessID: PropTypes.number,
119
35
  account: PropTypes.shape({
120
- generate_report_status: PropTypes.string,
121
- upload_report_status: PropTypes.string,
122
- report_file_paths: PropTypes.arrayOf(PropTypes.string),
36
+ id: PropTypes.number,
37
+ generate_task: PropTypes.shape({
38
+ id: PropTypes.string,
39
+ state: PropTypes.string,
40
+ result: PropTypes.string,
41
+ progress: PropTypes.number,
42
+ started_at: PropTypes.string,
43
+ ended_at: PropTypes.string,
44
+ duration: PropTypes.number,
45
+ report_file_path: PropTypes.string,
46
+ }),
123
47
  }),
124
- showFullScreen: PropTypes.bool,
125
- toggleFullScreen: PropTypes.func,
126
- activeTab: PropTypes.string,
48
+ onTaskStart: PropTypes.func,
127
49
  };
128
50
 
129
51
  Dashboard.defaultProps = {
130
- uploading: {},
131
- generating: {},
132
- startPolling: noop,
133
- fetchLogs: noop,
134
- stopPolling: noop,
135
- setActiveTab: noop,
136
- restartProcess: noop,
137
- downloadReports: noop,
138
- pollingProcessID: 0,
139
- account: {
140
- generate_report_status: 'unknown',
141
- upload_report_status: 'unknown',
142
- report_file_paths: [],
143
- },
144
- showFullScreen: false,
145
- toggleFullScreen: noop,
146
- activeTab: 'generating',
52
+ account: null,
53
+ onTaskStart: null,
147
54
  };
148
55
 
149
56
  export default Dashboard;
@@ -1,24 +1,67 @@
1
1
  import React from 'react';
2
- import { shallow, testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
+ import { shallow } from '@theforeman/test';
3
3
  import Dashboard from '../Dashboard';
4
- import { props } from '../Dashboard.fixtures';
5
-
6
- const fixtures = {
7
- 'with props': props,
8
- };
9
4
 
10
5
  describe('Dashboard', () => {
11
- describe('rendering', () =>
12
- testComponentSnapshotsWithFixtures(Dashboard, fixtures));
13
-
14
- it('componentWillUnmount should call "stopPolling"', () => {
15
- const stopPolling = jest.fn();
16
- const modifiedProps = {
17
- ...props,
18
- stopPolling,
6
+ it('should render TaskProgress component with correct props', () => {
7
+ const account = {
8
+ id: 1,
9
+ generate_task: {
10
+ id: 'task-1',
11
+ state: 'running',
12
+ result: null,
13
+ progress: 50,
14
+ },
19
15
  };
20
- const wrapper = shallow(<Dashboard {...modifiedProps} />);
21
- wrapper.unmount();
22
- expect(stopPolling).toBeCalled();
16
+ const onTaskStart = jest.fn();
17
+
18
+ const wrapper = shallow(
19
+ <Dashboard account={account} onTaskStart={onTaskStart} />
20
+ );
21
+
22
+ const taskProgress = wrapper.find('TaskProgress');
23
+ expect(taskProgress).toHaveLength(1);
24
+ expect(taskProgress.prop('task')).toEqual(account.generate_task);
25
+ expect(taskProgress.prop('title')).toBe('Report Generation');
26
+ expect(taskProgress.prop('organizationId')).toBe(1);
27
+ expect(taskProgress.prop('taskType')).toBe('generate');
28
+ expect(taskProgress.prop('onTaskStart')).toBe(onTaskStart);
29
+ });
30
+
31
+ it('should handle missing account gracefully', () => {
32
+ const wrapper = shallow(<Dashboard account={null} onTaskStart={null} />);
33
+
34
+ const taskProgress = wrapper.find('TaskProgress');
35
+ expect(taskProgress).toHaveLength(1);
36
+ expect(taskProgress.prop('task')).toBeNull();
37
+ expect(taskProgress.prop('organizationId')).toBeNull();
38
+ expect(taskProgress.prop('emptyMessage')).toBe(
39
+ 'No account data available.'
40
+ );
41
+ });
42
+
43
+ it('should handle missing generate_task gracefully', () => {
44
+ const account = { id: 1, generate_task: null };
45
+ const wrapper = shallow(<Dashboard account={account} onTaskStart={null} />);
46
+
47
+ const taskProgress = wrapper.find('TaskProgress');
48
+ expect(taskProgress).toHaveLength(1);
49
+ expect(taskProgress.prop('task')).toBeNull();
50
+ expect(taskProgress.prop('organizationId')).toBe(1);
51
+ });
52
+
53
+ it('should handle missing account.id gracefully', () => {
54
+ const account = {
55
+ generate_task: {
56
+ id: 'task-1',
57
+ state: 'running',
58
+ },
59
+ };
60
+ const wrapper = shallow(<Dashboard account={account} onTaskStart={null} />);
61
+
62
+ const taskProgress = wrapper.find('TaskProgress');
63
+ expect(taskProgress).toHaveLength(1);
64
+ expect(taskProgress.prop('organizationId')).toBeNull();
65
+ expect(taskProgress.prop('task')).toEqual(account.generate_task);
23
66
  });
24
67
  });
@@ -1,34 +1 @@
1
- import { bindActionCreators } from 'redux';
2
- import { connect } from 'react-redux';
3
-
4
- import * as actions from './DashboardActions';
5
- import { restartProcess } from '../AccountList/AccountListActions';
6
- import reducer from './DashboardReducer';
7
-
8
- import Dashboard from './Dashboard';
9
- import {
10
- selectUploading,
11
- selectGenerating,
12
- selectPollingProcessID,
13
- selectActiveTab,
14
- selectShowFullScreen,
15
- } from './DashboardSelectors';
16
-
17
- // map state to props
18
- const mapStateToProps = (state, { accountID }) => ({
19
- uploading: selectUploading(state, accountID),
20
- generating: selectGenerating(state, accountID),
21
- pollingProcessID: selectPollingProcessID(state, accountID),
22
- activeTab: selectActiveTab(state, accountID),
23
- showFullScreen: selectShowFullScreen(state, accountID),
24
- });
25
-
26
- // map action dispatchers to props
27
- const mapDispatchToProps = dispatch =>
28
- bindActionCreators({ ...actions, restartProcess }, dispatch);
29
-
30
- // export reducers
31
- export const reducers = { dashboard: reducer };
32
-
33
- // export connected component
34
- export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
1
+ export { default } from './Dashboard';
@@ -33,7 +33,6 @@ Object {
33
33
  "error": null,
34
34
  "pollingProcessID": 0,
35
35
  },
36
- "dashboard": Object {},
37
36
  "inventoryFilter": Object {
38
37
  "filterTerm": "some-org",
39
38
  },
@@ -8,19 +8,12 @@ import {
8
8
  TabContent,
9
9
  TabPane,
10
10
  Icon,
11
- noop,
12
11
  } from 'patternfly-react';
13
12
  import { translate as __ } from 'foremanReact/common/I18n';
14
13
  import './navContainer.scss';
15
- import FullScreenModal from '../FullScreenModal';
16
14
  import { selectSubscriptionConnectionEnabled } from '../InventorySettings/InventorySettingsSelectors';
17
15
 
18
- const NavContainer = ({
19
- items,
20
- showFullScreen,
21
- toggleFullScreen,
22
- terminalProps,
23
- }) => {
16
+ const NavContainer = ({ items }) => {
24
17
  const subscriptionConnectionEnabled = useSelector(
25
18
  selectSubscriptionConnectionEnabled
26
19
  );
@@ -50,11 +43,6 @@ const NavContainer = ({
50
43
  <div className="dashboard">
51
44
  <Nav bsClass="nav nav-tabs nav-tabs-pf">{navItems}</Nav>
52
45
  <TabContent animation>{tabComponents}</TabContent>
53
- <FullScreenModal
54
- showFullScreen={showFullScreen}
55
- toggleFullScreen={toggleFullScreen}
56
- terminalProps={terminalProps}
57
- />
58
46
  </div>
59
47
  </TabContainer>
60
48
  );
@@ -69,23 +57,10 @@ NavContainer.propTypes = {
69
57
  onClick: PropTypes.func,
70
58
  })
71
59
  ),
72
- showFullScreen: PropTypes.bool,
73
- toggleFullScreen: PropTypes.func,
74
- terminalProps: PropTypes.shape({
75
- exitCode: PropTypes.string,
76
- logs: PropTypes.oneOfType([
77
- PropTypes.arrayOf(PropTypes.string),
78
- PropTypes.string,
79
- ]),
80
- error: PropTypes.string,
81
- }),
82
60
  };
83
61
 
84
62
  NavContainer.defaultProps = {
85
63
  items: [],
86
- showFullScreen: false,
87
- toggleFullScreen: noop,
88
- terminalProps: {},
89
64
  };
90
65
 
91
66
  export default NavContainer;