foreman_leapp 3.1.0 → 3.3.0

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/foreman_leapp/locale/de/foreman_leapp.js +5 -2
  3. data/app/assets/javascripts/foreman_leapp/locale/en/foreman_leapp.js +5 -2
  4. data/app/assets/javascripts/foreman_leapp/locale/fr/foreman_leapp.js +7 -4
  5. data/app/assets/javascripts/foreman_leapp/locale/ja/foreman_leapp.js +9 -6
  6. data/app/assets/javascripts/foreman_leapp/locale/ka/foreman_leapp.js +6 -3
  7. data/app/assets/javascripts/foreman_leapp/locale/ko/foreman_leapp.js +7 -4
  8. data/app/assets/javascripts/foreman_leapp/locale/zh_CN/foreman_leapp.js +7 -4
  9. data/app/views/api/v2/preupgrade_report_entries/base.json.rabl +1 -1
  10. data/lib/foreman_leapp/engine.rb +2 -0
  11. data/lib/foreman_leapp/version.rb +1 -1
  12. data/locale/de/LC_MESSAGES/foreman_leapp.mo +0 -0
  13. data/locale/de/foreman_leapp.po +5 -2
  14. data/locale/en/LC_MESSAGES/foreman_leapp.mo +0 -0
  15. data/locale/en/foreman_leapp.po +5 -2
  16. data/locale/foreman_leapp.pot +36 -9
  17. data/locale/fr/LC_MESSAGES/foreman_leapp.mo +0 -0
  18. data/locale/fr/foreman_leapp.po +8 -5
  19. data/locale/ja/LC_MESSAGES/foreman_leapp.mo +0 -0
  20. data/locale/ja/foreman_leapp.po +10 -7
  21. data/locale/ka/LC_MESSAGES/foreman_leapp.mo +0 -0
  22. data/locale/ka/foreman_leapp.po +6 -3
  23. data/locale/ko/LC_MESSAGES/foreman_leapp.mo +0 -0
  24. data/locale/ko/foreman_leapp.po +8 -5
  25. data/locale/zh_CN/LC_MESSAGES/foreman_leapp.mo +0 -0
  26. data/locale/zh_CN/foreman_leapp.po +8 -5
  27. data/webpack/components/PreupgradeReports/PreupgradeReports.js +1 -1
  28. data/webpack/components/PreupgradeReports/PreupgradeReportsHelpers.js +2 -2
  29. data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReports.test.js.snap +1 -1
  30. data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReportsHelpers.test.js.snap +25 -1
  31. data/webpack/components/PreupgradeReports/components/__snapshots__/NoReports.test.js.snap +6 -0
  32. data/webpack/components/PreupgradeReportsList/__tests__/PreupgradeReportsList.test.js +119 -35
  33. data/webpack/components/PreupgradeReportsList/index.js +2 -3
  34. data/webpack/components/PreupgradeReportsTable/PreupgradeReportsTable.scss +5 -0
  35. data/webpack/components/PreupgradeReportsTable/ReportDetails.js +134 -0
  36. data/webpack/components/PreupgradeReportsTable/__tests__/PreupgradeReportsTable.test.js +186 -0
  37. data/webpack/components/PreupgradeReportsTable/index.js +237 -0
  38. data/webpack/global_index.js +10 -0
  39. metadata +8 -8
  40. data/webpack/__mocks__/foremanReact/common/I18n.js +0 -2
  41. data/webpack/__mocks__/foremanReact/components/Pagination.js +0 -2
  42. data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +0 -1
  43. data/webpack/__mocks__/foremanReact/components/common/MessageBox.js +0 -2
  44. data/webpack/components/PreupgradeReportsList/__tests__/__snapshots__/PreupgradeReportsList.test.js.snap +0 -135
@@ -0,0 +1,237 @@
1
+ import PropTypes from 'prop-types';
2
+ import React, { useEffect, useState } from 'react';
3
+ import { useDispatch } from 'react-redux';
4
+ import { ExpandableSection, Tooltip } from '@patternfly/react-core';
5
+ import { ExpandableRowContent, Tbody, Td, Tr } from '@patternfly/react-table';
6
+ import { translate as __ } from 'foremanReact/common/I18n';
7
+ import { Table } from 'foremanReact/components/PF4/TableIndexPage/Table/Table';
8
+ import { getColumnHelpers } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
9
+ import { APIActions } from 'foremanReact/redux/API';
10
+ import { STATUS } from 'foremanReact/constants';
11
+ import { entriesPage } from '../PreupgradeReports/PreupgradeReportsHelpers';
12
+ import ReportDetails, { renderSeverityLabel } from './ReportDetails';
13
+
14
+ const PreupgradeReportsTable = ({ data = {} }) => {
15
+ const [error, setError] = useState(null);
16
+
17
+ const [isReportExpanded, setIsReportExpanded] = useState(false); // Outer expansion state (Leapp Report Section)
18
+ const [pagination, setPagination] = useState({ page: 1, perPage: 5 });
19
+ const [reportData, setReportData] = useState(null);
20
+ const [status, setStatus] = useState(STATUS.RESOLVED);
21
+ const [expandedRowIds, setExpandedRowIds] = useState(new Set()); // Inner table expansion state (Rows)
22
+
23
+ const dispatch = useDispatch();
24
+ // eslint-disable-next-line camelcase
25
+ const isLeappJob = data?.template_name?.includes('Run preupgrade via Leapp');
26
+
27
+ const columns = {
28
+ title: {
29
+ title: __('Title'),
30
+ },
31
+ host: {
32
+ title: __('Host'),
33
+ wrapper: entry =>
34
+ entry.hostname || (reportData && reportData.hostname) || '-',
35
+ },
36
+ risk_factor: {
37
+ title: __('Risk Factor'),
38
+ wrapper: ({ severity }) => renderSeverityLabel(severity),
39
+ },
40
+ has_remediation: {
41
+ title: __('Has Remediation?'),
42
+ wrapper: entry =>
43
+ entry.detail && entry.detail.remediations ? __('Yes') : __('No'),
44
+ },
45
+ inhibitor: {
46
+ title: __('Inhibitor?'),
47
+ wrapper: entry =>
48
+ entry.flags && entry.flags.some(flag => flag === 'inhibitor') ? (
49
+ <Tooltip content={__('This issue inhibits the upgrade.')}>
50
+ <span>{__('Yes')}</span>
51
+ </Tooltip>
52
+ ) : (
53
+ __('No')
54
+ ),
55
+ },
56
+ };
57
+
58
+ useEffect(() => {
59
+ let isMounted = true;
60
+ if (!isLeappJob || !isReportExpanded || reportData) {
61
+ return undefined;
62
+ }
63
+ setStatus(STATUS.PENDING);
64
+
65
+ dispatch(
66
+ APIActions.get({
67
+ key: `GET_LEAPP_REPORT_LIST_${data.id}`,
68
+ url: `/api/job_invocations/${data.id}/preupgrade_reports`,
69
+ handleSuccess: listResponse => {
70
+ if (!isMounted) return;
71
+ const listPayload = listResponse.data || listResponse;
72
+ const summary = listPayload.results?.[0];
73
+ if (summary?.id) {
74
+ dispatch(
75
+ APIActions.get({
76
+ key: `GET_LEAPP_REPORT_DETAIL_${summary.id}`,
77
+ url: `/api/preupgrade_reports/${summary.id}`,
78
+ handleSuccess: detailResponse => {
79
+ if (isMounted) {
80
+ const detailPayload = detailResponse.data || detailResponse;
81
+ setReportData(detailPayload);
82
+ setStatus(STATUS.RESOLVED);
83
+ }
84
+ },
85
+ handleError: err => {
86
+ if (isMounted) {
87
+ setError(err);
88
+ setStatus(STATUS.ERROR);
89
+ }
90
+ },
91
+ })
92
+ );
93
+ } else if (isMounted) {
94
+ setReportData({});
95
+ setStatus(STATUS.RESOLVED);
96
+ }
97
+ },
98
+ handleError: err => {
99
+ if (isMounted) {
100
+ setError(err);
101
+ setStatus(STATUS.ERROR);
102
+ }
103
+ },
104
+ })
105
+ );
106
+
107
+ return () => {
108
+ isMounted = false;
109
+ };
110
+ }, [isReportExpanded, data.id, isLeappJob, reportData, dispatch]);
111
+
112
+ // eslint-disable-next-line camelcase
113
+ const entries = reportData?.preupgrade_report_entries || [];
114
+ const pagedEntries = entriesPage(entries, pagination);
115
+
116
+ const handleParamsChange = newParams => {
117
+ setPagination(prev => ({
118
+ ...prev,
119
+ page: newParams.page || prev.page,
120
+ perPage: newParams.per_page || prev.perPage,
121
+ }));
122
+ setExpandedRowIds(new Set());
123
+ };
124
+
125
+ const toggleRowExpansion = (id, isExpanding) => {
126
+ setExpandedRowIds(prev => {
127
+ const newSet = new Set(prev);
128
+ if (isExpanding) {
129
+ newSet.add(id);
130
+ } else {
131
+ newSet.delete(id);
132
+ }
133
+ return newSet;
134
+ });
135
+ };
136
+
137
+ const areAllRowsExpanded =
138
+ pagedEntries.length > 0 &&
139
+ pagedEntries.every(entry => expandedRowIds.has(entry.id));
140
+
141
+ const onExpandAll = () => {
142
+ setExpandedRowIds(() => {
143
+ if (areAllRowsExpanded) {
144
+ return new Set();
145
+ }
146
+ return new Set(pagedEntries.map(e => e.id));
147
+ });
148
+ };
149
+
150
+ const [columnKeys, keysToColumnNames] = getColumnHelpers(columns);
151
+
152
+ if (!isLeappJob) return null;
153
+
154
+ return (
155
+ <ExpandableSection
156
+ className="leapp-report-section"
157
+ isExpanded={isReportExpanded}
158
+ onToggle={(_event, val) => setIsReportExpanded(val)}
159
+ toggleText={__('Leapp preupgrade report')}
160
+ >
161
+ <Table
162
+ ouiaId="leapp-report-table"
163
+ columns={columns}
164
+ isEmbedded
165
+ params={{
166
+ page: pagination.page,
167
+ perPage: pagination.perPage,
168
+ order: '',
169
+ }}
170
+ results={pagedEntries}
171
+ itemCount={entries.length}
172
+ url=""
173
+ isPending={status === STATUS.PENDING}
174
+ errorMessage={
175
+ status === STATUS.ERROR && error?.message ? error.message : null
176
+ }
177
+ showCheckboxes={false}
178
+ refreshData={() => {}}
179
+ isDeleteable={false}
180
+ emptyMessage={__('The preupgrade report shows no issues.')}
181
+ setParams={handleParamsChange}
182
+ childrenOutsideTbody
183
+ onExpandAll={onExpandAll}
184
+ // Inverted per PatternFly implementation to ensure correct toggle icon state
185
+ areAllRowsExpanded={!areAllRowsExpanded}
186
+ >
187
+ {pagedEntries.map((entry, rowIndex) => {
188
+ const isRowExpanded = expandedRowIds.has(entry.id);
189
+ return (
190
+ <Tbody key={entry.id} isExpanded={isRowExpanded}>
191
+ <Tr ouiaId={`table-row-${rowIndex}`}>
192
+ <Td
193
+ expand={{
194
+ rowIndex,
195
+ isExpanded: isRowExpanded,
196
+ onToggle: (_event, _rowIndex, isOpen) =>
197
+ toggleRowExpansion(entry.id, isOpen),
198
+ }}
199
+ />
200
+ {columnKeys.map(key => (
201
+ <Td key={key} dataLabel={keysToColumnNames[key]}>
202
+ {columns[key].wrapper
203
+ ? columns[key].wrapper(entry)
204
+ : entry[key]}
205
+ </Td>
206
+ ))}
207
+ </Tr>
208
+ <Tr
209
+ isExpanded={isRowExpanded}
210
+ ouiaId={`table-row-details-${rowIndex}`}
211
+ >
212
+ <Td colSpan={columnKeys.length + 1}>
213
+ <ExpandableRowContent>
214
+ {isRowExpanded && <ReportDetails entry={entry} />}
215
+ </ExpandableRowContent>
216
+ </Td>
217
+ </Tr>
218
+ </Tbody>
219
+ );
220
+ })}
221
+ </Table>
222
+ </ExpandableSection>
223
+ );
224
+ };
225
+
226
+ PreupgradeReportsTable.propTypes = {
227
+ data: PropTypes.shape({
228
+ id: PropTypes.number,
229
+ template_name: PropTypes.string,
230
+ }),
231
+ };
232
+
233
+ PreupgradeReportsTable.defaultProps = {
234
+ data: {},
235
+ };
236
+
237
+ export default PreupgradeReportsTable;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
3
+ import PreupgradeReportsTable from './components/PreupgradeReportsTable';
4
+
5
+ addGlobalFill(
6
+ 'job-invocation-additional-info',
7
+ 'leapp-preupgrade-report-fill',
8
+ <PreupgradeReportsTable key="leapp-report-fill" />,
9
+ 100
10
+ );
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_leapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Leapp team
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-10-29 00:00:00.000000000 Z
10
+ date: 2026-03-10 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: foreman_remote_execution
@@ -130,10 +130,6 @@ files:
130
130
  - test/unit/actions/preupgrade_job_test.rb
131
131
  - test/unit/helpers/job_helper_test.rb
132
132
  - webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js
133
- - webpack/__mocks__/foremanReact/common/I18n.js
134
- - webpack/__mocks__/foremanReact/components/Pagination.js
135
- - webpack/__mocks__/foremanReact/components/common/EmptyState.js
136
- - webpack/__mocks__/foremanReact/components/common/MessageBox.js
137
133
  - webpack/components/PreupgradeReports/PreupgradeReports.js
138
134
  - webpack/components/PreupgradeReports/PreupgradeReportsActions.js
139
135
  - webpack/components/PreupgradeReports/PreupgradeReportsHelpers.js
@@ -164,7 +160,6 @@ files:
164
160
  - webpack/components/PreupgradeReports/index.js
165
161
  - webpack/components/PreupgradeReportsList/PreupgradeReportList.scss
166
162
  - webpack/components/PreupgradeReportsList/__tests__/PreupgradeReportsList.test.js
167
- - webpack/components/PreupgradeReportsList/__tests__/__snapshots__/PreupgradeReportsList.test.js.snap
168
163
  - webpack/components/PreupgradeReportsList/components/EmptyInfoItem.js
169
164
  - webpack/components/PreupgradeReportsList/components/InfoItem.js
170
165
  - webpack/components/PreupgradeReportsList/components/InhibitorInfoItem.js
@@ -191,8 +186,13 @@ files:
191
186
  - webpack/components/PreupgradeReportsList/components/images/i_severity-low.svg
192
187
  - webpack/components/PreupgradeReportsList/components/images/i_severity-med.svg
193
188
  - webpack/components/PreupgradeReportsList/index.js
189
+ - webpack/components/PreupgradeReportsTable/PreupgradeReportsTable.scss
190
+ - webpack/components/PreupgradeReportsTable/ReportDetails.js
191
+ - webpack/components/PreupgradeReportsTable/__tests__/PreupgradeReportsTable.test.js
192
+ - webpack/components/PreupgradeReportsTable/index.js
194
193
  - webpack/consts.js
195
194
  - webpack/csrf.js
195
+ - webpack/global_index.js
196
196
  - webpack/index.js
197
197
  - webpack/reducer.js
198
198
  - webpack/testSetup.js
@@ -214,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
214
  - !ruby/object:Gem::Version
215
215
  version: '0'
216
216
  requirements: []
217
- rubygems_version: 3.6.9
217
+ rubygems_version: 4.0.3
218
218
  specification_version: 4
219
219
  summary: A Foreman plugin for Leapp utility.
220
220
  test_files:
@@ -1,2 +0,0 @@
1
- export const translate = val => val;
2
- export const sprintf = val => val;
@@ -1,2 +0,0 @@
1
- const Pagination = () => jest.fn();
2
- export default Pagination;
@@ -1 +0,0 @@
1
- export const EmptyStatePattern = () => jest.fn();
@@ -1,2 +0,0 @@
1
- const MessageBox = () => jest.fn();
2
- export default MessageBox;
@@ -1,135 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`PreupgradeReportsList should render 1`] = `
4
- <ListView
5
- className=""
6
- id="preupgrade-report-entries-list-view"
7
- >
8
- <PreupgradeReportsListHeader
9
- changeSort={[Function]}
10
- sort={
11
- Object {
12
- "attribute": "",
13
- "order": "asc",
14
- }
15
- }
16
- toggleSelectAll={[Function]}
17
- />
18
- <PreupgradeReportEntry
19
- entry={
20
- Object {
21
- "severity": "Too severe to talk about",
22
- "title": "Fix me!",
23
- }
24
- }
25
- isEntrySelected={false}
26
- key="0"
27
- toggleSelected={[Function]}
28
- />
29
- <PreupgradeReportEntry
30
- entry={
31
- Object {
32
- "severity": "medium",
33
- "title": "I am broken too",
34
- }
35
- }
36
- isEntrySelected={false}
37
- key="1"
38
- toggleSelected={[Function]}
39
- />
40
- <PreupgradeReportEntry
41
- entry={
42
- Object {
43
- "severity": "high",
44
- "title": "Octocat is not happy",
45
- }
46
- }
47
- isEntrySelected={false}
48
- key="2"
49
- toggleSelected={[Function]}
50
- />
51
- <PreupgradeReportEntry
52
- entry={
53
- Object {
54
- "severity": "low",
55
- "title": "Not enough credits",
56
- }
57
- }
58
- isEntrySelected={false}
59
- key="3"
60
- toggleSelected={[Function]}
61
- />
62
- <Pagination
63
- itemCount={4}
64
- onChange={[Function]}
65
- viewType="list"
66
- />
67
- </ListView>
68
- `;
69
-
70
- exports[`PreupgradeReportsList should render when working 1`] = `
71
- <ListView
72
- className=""
73
- id="preupgrade-report-entries-list-view"
74
- >
75
- <PreupgradeReportsListHeader
76
- changeSort={[Function]}
77
- sort={
78
- Object {
79
- "attribute": "",
80
- "order": "asc",
81
- }
82
- }
83
- toggleSelectAll={[Function]}
84
- />
85
- <PreupgradeReportEntry
86
- entry={
87
- Object {
88
- "severity": "Too severe to talk about",
89
- "title": "Fix me!",
90
- }
91
- }
92
- isEntrySelected={false}
93
- key="0"
94
- toggleSelected={[Function]}
95
- />
96
- <PreupgradeReportEntry
97
- entry={
98
- Object {
99
- "severity": "medium",
100
- "title": "I am broken too",
101
- }
102
- }
103
- isEntrySelected={false}
104
- key="1"
105
- toggleSelected={[Function]}
106
- />
107
- <PreupgradeReportEntry
108
- entry={
109
- Object {
110
- "severity": "high",
111
- "title": "Octocat is not happy",
112
- }
113
- }
114
- isEntrySelected={false}
115
- key="2"
116
- toggleSelected={[Function]}
117
- />
118
- <PreupgradeReportEntry
119
- entry={
120
- Object {
121
- "severity": "low",
122
- "title": "Not enough credits",
123
- }
124
- }
125
- isEntrySelected={false}
126
- key="3"
127
- toggleSelected={[Function]}
128
- />
129
- <Pagination
130
- itemCount={4}
131
- onChange={[Function]}
132
- viewType="list"
133
- />
134
- </ListView>
135
- `;