foreman_leapp 3.4.0 → 4.1.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.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/preupgrade_report_entries_controller.rb +120 -0
- data/app/controllers/api/v2/preupgrade_reports_controller.rb +2 -2
- data/app/models/preupgrade_report_entry.rb +73 -1
- data/app/views/api/v2/preupgrade_report_entries/index.json.rabl +4 -0
- data/app/views/api/v2/preupgrade_reports/show.json.rabl +2 -5
- data/config/routes.rb +17 -3
- data/lib/foreman_leapp/engine.rb +1 -1
- data/lib/foreman_leapp/version.rb +1 -1
- data/test/functional/api/v2/preupgrade_report_entries_controller_test.rb +258 -0
- data/test/functional/api/v2/preupgrade_reports_controller_test.rb +7 -5
- data/test/models/preupgrade_report_entry_test.rb +47 -0
- data/webpack/components/PreupgradeReports/PreupgradeReports.js +11 -4
- data/webpack/components/PreupgradeReports/__tests__/PreupgradeReports.fixtures.js +43 -0
- data/webpack/components/PreupgradeReports/__tests__/PreupgradeReports.test.js +151 -46
- data/webpack/components/PreupgradeReports/components/NoReports.test.js +26 -12
- data/webpack/components/PreupgradeReportsTable/PreupgradeReportsTable.scss +9 -1
- data/webpack/components/PreupgradeReportsTable/PreupgradeReportsTableHelpers.js +164 -0
- data/webpack/components/PreupgradeReportsTable/__tests__/PreupgradeReportsTable.test.js +245 -38
- data/webpack/components/PreupgradeReportsTable/index.js +337 -238
- metadata +7 -4
- data/webpack/components/PreupgradeReports/__tests__/__snapshots__/PreupgradeReports.test.js.snap +0 -121
- data/webpack/components/PreupgradeReports/components/__snapshots__/NoReports.test.js.snap +0 -25
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* eslint-disable max-lines */
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import React, {
|
|
4
|
-
|
|
5
|
-
useEffect,
|
|
4
|
+
useState,
|
|
6
5
|
useMemo,
|
|
6
|
+
useCallback,
|
|
7
7
|
useRef,
|
|
8
|
-
|
|
8
|
+
useEffect,
|
|
9
9
|
} from 'react';
|
|
10
10
|
import { useDispatch } from 'react-redux';
|
|
11
11
|
import {
|
|
@@ -25,17 +25,14 @@ import SelectAllCheckbox from 'foremanReact/components/PF4/TableIndexPage/Table/
|
|
|
25
25
|
import { useBulkSelect } from 'foremanReact/components/PF4/TableIndexPage/Table/TableHooks';
|
|
26
26
|
import { RowSelectTd } from 'foremanReact/components/PF4/TableIndexPage/RowSelectTd';
|
|
27
27
|
import { getColumnHelpers } from 'foremanReact/components/PF4/TableIndexPage/Table/helpers';
|
|
28
|
+
import { getControllerSearchProps, STATUS } from 'foremanReact/constants';
|
|
29
|
+
import SearchBar from 'foremanReact/components/SearchBar';
|
|
28
30
|
import { APIActions } from 'foremanReact/redux/API';
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
entriesPage,
|
|
32
|
-
entryFixable,
|
|
33
|
-
} from '../PreupgradeReports/PreupgradeReportsHelpers';
|
|
31
|
+
import { usePreupgradeTableState } from './PreupgradeReportsTableHelpers';
|
|
32
|
+
import { entryFixable } from '../PreupgradeReports/PreupgradeReportsHelpers';
|
|
34
33
|
import ReportDetails, { renderSeverityLabel } from './ReportDetails';
|
|
35
34
|
import './PreupgradeReportsTable.scss';
|
|
36
35
|
|
|
37
|
-
const LEAPP_TEMPLATE_NAME = 'Run preupgrade via Leapp';
|
|
38
|
-
|
|
39
36
|
const isRowFixable = entryFixable;
|
|
40
37
|
|
|
41
38
|
const submitJobInvocation = (
|
|
@@ -43,8 +40,12 @@ const submitJobInvocation = (
|
|
|
43
40
|
setError,
|
|
44
41
|
feature,
|
|
45
42
|
hostIds,
|
|
46
|
-
remediationIds
|
|
43
|
+
remediationIds,
|
|
44
|
+
setIsSubmitting
|
|
47
45
|
) => {
|
|
46
|
+
setError(null);
|
|
47
|
+
setIsSubmitting(true);
|
|
48
|
+
|
|
48
49
|
const payload = {
|
|
49
50
|
job_invocation: {
|
|
50
51
|
feature,
|
|
@@ -64,168 +65,131 @@ const submitJobInvocation = (
|
|
|
64
65
|
const result = response.data || response;
|
|
65
66
|
if (result?.id) {
|
|
66
67
|
window.location.assign(foremanUrl(`/job_invocations/${result.id}`));
|
|
68
|
+
} else {
|
|
69
|
+
setIsSubmitting(false);
|
|
67
70
|
}
|
|
68
71
|
},
|
|
69
|
-
handleError: err =>
|
|
72
|
+
handleError: err => {
|
|
73
|
+
setError(err);
|
|
74
|
+
setIsSubmitting(false);
|
|
75
|
+
},
|
|
70
76
|
})
|
|
71
77
|
);
|
|
72
78
|
};
|
|
73
79
|
|
|
74
80
|
const PreupgradeReportsTable = ({ data = {} }) => {
|
|
75
|
-
const [error, setError] = useState(null);
|
|
76
81
|
const [isReportExpanded, setIsReportExpanded] = useState(false);
|
|
77
|
-
const [
|
|
78
|
-
const [
|
|
79
|
-
const [
|
|
80
|
-
const [expandedRowIds, setExpandedRowIds] = useState(new Set());
|
|
81
|
-
|
|
82
|
+
const [submitError, setSubmitError] = useState(null);
|
|
83
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
84
|
+
const [fixableCount, setFixableCount] = useState(null);
|
|
82
85
|
const dispatch = useDispatch();
|
|
83
|
-
|
|
84
|
-
const isLeappJob = data?.template_name?.includes(LEAPP_TEMPLATE_NAME);
|
|
86
|
+
const hasLoadedDataRef = useRef(false);
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
const {
|
|
89
|
+
isLeappJob,
|
|
90
|
+
status,
|
|
91
|
+
error,
|
|
92
|
+
reportId,
|
|
93
|
+
rows,
|
|
94
|
+
totalCount,
|
|
95
|
+
pagination,
|
|
96
|
+
sortBy,
|
|
97
|
+
searchValue,
|
|
98
|
+
setSearchValue,
|
|
99
|
+
setPagination,
|
|
100
|
+
setSortBy,
|
|
101
|
+
expandedRowIds,
|
|
102
|
+
toggleRowExpansion,
|
|
103
|
+
areAllRowsExpanded,
|
|
104
|
+
onExpandAll,
|
|
105
|
+
} = usePreupgradeTableState(data, isReportExpanded);
|
|
106
|
+
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (totalCount > 0 && !hasLoadedDataRef.current) {
|
|
109
|
+
hasLoadedDataRef.current = true;
|
|
110
|
+
}
|
|
111
|
+
}, [totalCount]);
|
|
112
|
+
const hasData = totalCount > 0 || hasLoadedDataRef.current;
|
|
88
113
|
|
|
89
|
-
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
setFixableCount(null);
|
|
116
|
+
}, [searchValue, reportId]);
|
|
117
|
+
|
|
118
|
+
const searchProps = useMemo(() => {
|
|
119
|
+
if (!reportId) return null;
|
|
120
|
+
const baseProps = getControllerSearchProps('preupgrade_report_entries');
|
|
121
|
+
return {
|
|
122
|
+
...baseProps,
|
|
123
|
+
autocomplete: {
|
|
124
|
+
...baseProps.autocomplete,
|
|
125
|
+
url: foremanUrl(
|
|
126
|
+
`/api/v2/preupgrade_reports/${reportId}/preupgrade_report_entries/auto_complete_search`
|
|
127
|
+
),
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}, [reportId]);
|
|
90
131
|
|
|
91
132
|
const columns = useMemo(
|
|
92
133
|
() => ({
|
|
93
|
-
title: {
|
|
94
|
-
|
|
134
|
+
title: {
|
|
135
|
+
title: __('Title'),
|
|
136
|
+
isSorted: true,
|
|
137
|
+
width: 30,
|
|
138
|
+
},
|
|
139
|
+
hostname: {
|
|
95
140
|
title: __('Host'),
|
|
96
|
-
wrapper:
|
|
141
|
+
wrapper: e => e.hostname || '-',
|
|
142
|
+
isSorted: true,
|
|
143
|
+
width: 20,
|
|
97
144
|
},
|
|
98
145
|
risk_factor: {
|
|
99
146
|
title: __('Risk Factor'),
|
|
100
147
|
wrapper: ({ severity }) => renderSeverityLabel(severity),
|
|
148
|
+
isSorted: true,
|
|
149
|
+
width: 15,
|
|
101
150
|
},
|
|
102
151
|
has_remediation: {
|
|
103
152
|
title: __('Has Remediation?'),
|
|
104
|
-
wrapper:
|
|
153
|
+
wrapper: e => (e.detail?.remediations ? __('Yes') : __('No')),
|
|
154
|
+
isSorted: true,
|
|
155
|
+
width: 20,
|
|
105
156
|
},
|
|
106
157
|
inhibitor: {
|
|
107
158
|
title: __('Inhibitor?'),
|
|
108
|
-
wrapper:
|
|
109
|
-
|
|
159
|
+
wrapper: e =>
|
|
160
|
+
e.flags?.includes('inhibitor') ? (
|
|
110
161
|
<Tooltip content={__('This issue inhibits the upgrade.')}>
|
|
111
162
|
<span>{__('Yes')}</span>
|
|
112
163
|
</Tooltip>
|
|
113
164
|
) : (
|
|
114
165
|
__('No')
|
|
115
166
|
),
|
|
167
|
+
isSorted: true,
|
|
168
|
+
width: 15,
|
|
116
169
|
},
|
|
117
170
|
}),
|
|
118
|
-
|
|
119
|
-
[reportData?.hostname]
|
|
171
|
+
[]
|
|
120
172
|
);
|
|
121
173
|
|
|
122
|
-
|
|
123
|
-
let isMounted = true;
|
|
124
|
-
const fetchKey = `${data.id}:${jobStatusLabel}`;
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
!isLeappJob ||
|
|
128
|
-
!isReportExpanded ||
|
|
129
|
-
lastFetchedKeyRef.current === fetchKey
|
|
130
|
-
)
|
|
131
|
-
return undefined;
|
|
132
|
-
|
|
133
|
-
const fail = err => {
|
|
134
|
-
if (!isMounted) return;
|
|
135
|
-
setError(err);
|
|
136
|
-
setStatus(STATUS.ERROR);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
const succeed = response => {
|
|
140
|
-
if (!isMounted) return;
|
|
141
|
-
lastFetchedKeyRef.current = fetchKey;
|
|
142
|
-
setReportData(response?.data || response || null);
|
|
143
|
-
setStatus(STATUS.RESOLVED);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
setStatus(STATUS.PENDING);
|
|
147
|
-
dispatch(
|
|
148
|
-
APIActions.get({
|
|
149
|
-
key: `GET_LEAPP_REPORT_LIST_${data.id}`,
|
|
150
|
-
url: `/api/job_invocations/${data.id}/preupgrade_reports`,
|
|
151
|
-
handleSuccess: listResponse => {
|
|
152
|
-
if (!isMounted) return;
|
|
153
|
-
const summary = (listResponse.data || listResponse).results?.[0];
|
|
154
|
-
if (summary?.id) {
|
|
155
|
-
dispatch(
|
|
156
|
-
APIActions.get({
|
|
157
|
-
key: `GET_LEAPP_REPORT_DETAIL_${summary.id}`,
|
|
158
|
-
url: `/api/preupgrade_reports/${summary.id}`,
|
|
159
|
-
handleSuccess: detailResponse => succeed(detailResponse),
|
|
160
|
-
handleError: err => fail(err),
|
|
161
|
-
})
|
|
162
|
-
);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
succeed(null);
|
|
166
|
-
},
|
|
167
|
-
handleError: err => fail(err),
|
|
168
|
-
})
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
return () => {
|
|
172
|
-
isMounted = false;
|
|
173
|
-
};
|
|
174
|
-
}, [isReportExpanded, data.id, isLeappJob, dispatch, jobStatusLabel]);
|
|
175
|
-
|
|
176
|
-
// eslint-disable-next-line camelcase
|
|
177
|
-
const entries = useMemo(() => reportData?.preupgrade_report_entries || [], [
|
|
178
|
-
reportData,
|
|
179
|
-
]);
|
|
180
|
-
|
|
181
|
-
const pagedEntries = useMemo(
|
|
182
|
-
() => entriesPage(entries, pagination),
|
|
183
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
184
|
-
[entries, pagination.page, pagination.perPage]
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
const getHostId = useCallback(
|
|
188
|
-
entry =>
|
|
189
|
-
entry.host_id ||
|
|
190
|
-
entry.hostId ||
|
|
191
|
-
// eslint-disable-next-line camelcase
|
|
192
|
-
reportData?.host_id ||
|
|
193
|
-
reportData?.host?.id ||
|
|
194
|
-
// eslint-disable-next-line camelcase
|
|
195
|
-
data?.targeting?.host_id,
|
|
196
|
-
[reportData, data]
|
|
197
|
-
);
|
|
174
|
+
const pagedFixableEntries = useMemo(() => rows.filter(isRowFixable), [rows]);
|
|
198
175
|
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}, []);
|
|
207
|
-
|
|
208
|
-
const toggleRowExpansion = useCallback((id, isExpanding) => {
|
|
209
|
-
setExpandedRowIds(prev => {
|
|
210
|
-
const next = new Set(prev);
|
|
211
|
-
if (isExpanding) next.add(id);
|
|
212
|
-
else next.delete(id);
|
|
213
|
-
return next;
|
|
214
|
-
});
|
|
215
|
-
}, []);
|
|
216
|
-
|
|
217
|
-
const { inclusionSet, exclusionSet, ...selectAllOptions } = useBulkSelect({
|
|
218
|
-
results: pagedEntries,
|
|
176
|
+
const {
|
|
177
|
+
inclusionSet,
|
|
178
|
+
exclusionSet,
|
|
179
|
+
selectedCount,
|
|
180
|
+
...selectAllOptions
|
|
181
|
+
} = useBulkSelect({
|
|
182
|
+
results: pagedFixableEntries,
|
|
219
183
|
metadata: {
|
|
220
|
-
total:
|
|
184
|
+
total: totalCount,
|
|
221
185
|
page: pagination.page,
|
|
222
|
-
selectable:
|
|
186
|
+
selectable: fixableCount,
|
|
223
187
|
},
|
|
224
|
-
initialSearchQuery:
|
|
188
|
+
initialSearchQuery: searchValue,
|
|
225
189
|
});
|
|
226
190
|
|
|
227
191
|
const {
|
|
228
|
-
selectAll,
|
|
192
|
+
selectAll: originalSelectAll,
|
|
229
193
|
selectPage,
|
|
230
194
|
selectNone,
|
|
231
195
|
selectOne,
|
|
@@ -233,141 +197,266 @@ const PreupgradeReportsTable = ({ data = {} }) => {
|
|
|
233
197
|
isSelected,
|
|
234
198
|
} = selectAllOptions;
|
|
235
199
|
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
200
|
+
const selectAll = useCallback(
|
|
201
|
+
(...args) => {
|
|
202
|
+
// Get count of all fixable entries before selecting
|
|
203
|
+
if (fixableCount === null) {
|
|
204
|
+
dispatch(
|
|
205
|
+
APIActions.get({
|
|
206
|
+
key: `GET_FIXABLE_COUNT_${reportId}`,
|
|
207
|
+
url: `/api/v2/preupgrade_reports/${reportId}/preupgrade_report_entries`,
|
|
208
|
+
params: {
|
|
209
|
+
search: [searchValue, 'fix_type = command']
|
|
210
|
+
.filter(Boolean)
|
|
211
|
+
.join(' AND '),
|
|
212
|
+
per_page: 0,
|
|
213
|
+
},
|
|
214
|
+
handleSuccess: res => {
|
|
215
|
+
const payload = res.data || res;
|
|
216
|
+
const count = payload.subtotal ?? 0;
|
|
217
|
+
setFixableCount(count);
|
|
218
|
+
originalSelectAll(...args);
|
|
219
|
+
},
|
|
220
|
+
handleError: () => {
|
|
221
|
+
setFixableCount(0);
|
|
222
|
+
},
|
|
223
|
+
})
|
|
224
|
+
);
|
|
225
|
+
} else {
|
|
226
|
+
originalSelectAll(...args);
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
[dispatch, reportId, searchValue, fixableCount, originalSelectAll]
|
|
251
230
|
);
|
|
252
231
|
|
|
253
|
-
const
|
|
254
|
-
pagedEntries,
|
|
255
|
-
]);
|
|
232
|
+
const selectedIds = Array.from(inclusionSet);
|
|
256
233
|
|
|
257
234
|
const areAllPageFixableSelected =
|
|
258
235
|
pagedFixableEntries.length > 0 &&
|
|
259
|
-
pagedFixableEntries.every(e =>
|
|
260
|
-
|
|
261
|
-
const areAllFixableSelected =
|
|
262
|
-
validFixableIds.length > 0 &&
|
|
263
|
-
validFixableIds.every(id => selectedIds.includes(id));
|
|
264
|
-
|
|
265
|
-
const areAllRowsExpanded =
|
|
266
|
-
pagedEntries.length > 0 &&
|
|
267
|
-
pagedEntries.every(entry => expandedRowIds.has(entry.id));
|
|
236
|
+
pagedFixableEntries.every(e => inclusionSet.has(e.id));
|
|
268
237
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
areAllRowsExpanded ? new Set() : new Set(pagedEntries.map(e => e.id))
|
|
272
|
-
);
|
|
273
|
-
}, [areAllRowsExpanded, pagedEntries]);
|
|
238
|
+
// eslint-disable-next-line camelcase
|
|
239
|
+
const globalHostId = data?.targeting?.host_id;
|
|
274
240
|
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
241
|
+
const getHostId = useCallback(
|
|
242
|
+
// eslint-disable-next-line camelcase
|
|
243
|
+
entry => entry.host_id || entry.hostId || globalHostId,
|
|
244
|
+
[globalHostId]
|
|
278
245
|
);
|
|
279
246
|
|
|
280
247
|
const hostIdsForSelected = useMemo(
|
|
281
248
|
() =>
|
|
282
249
|
Array.from(
|
|
283
250
|
new Set(
|
|
284
|
-
|
|
251
|
+
rows
|
|
285
252
|
.filter(e => selectedIds.includes(e.id))
|
|
286
253
|
.map(getHostId)
|
|
287
254
|
.filter(Boolean)
|
|
288
255
|
)
|
|
289
256
|
),
|
|
290
|
-
[
|
|
257
|
+
[rows, selectedIds, getHostId]
|
|
291
258
|
);
|
|
292
259
|
|
|
293
260
|
const allHostIds = useMemo(
|
|
294
|
-
() => Array.from(new Set(
|
|
295
|
-
[
|
|
261
|
+
() => Array.from(new Set(rows.map(getHostId).filter(Boolean))),
|
|
262
|
+
[rows, getHostId]
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
const handleParamsChange = useCallback(
|
|
266
|
+
newParams => {
|
|
267
|
+
let sortChanged = false;
|
|
268
|
+
if (newParams.order !== undefined) {
|
|
269
|
+
const parts = newParams.order.split(' ');
|
|
270
|
+
const newIndex = parts[0] || '';
|
|
271
|
+
const newDirection = (parts[1] || 'ASC').toLowerCase();
|
|
272
|
+
sortChanged =
|
|
273
|
+
newIndex !== sortBy.index || newDirection !== sortBy.direction;
|
|
274
|
+
if (sortChanged)
|
|
275
|
+
setSortBy({ index: newIndex, direction: newDirection });
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let newPage = pagination.page;
|
|
279
|
+
if (sortChanged) {
|
|
280
|
+
newPage = 1;
|
|
281
|
+
} else if (newParams.page !== undefined) {
|
|
282
|
+
newPage = Number(newParams.page);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// eslint-disable-next-line camelcase
|
|
286
|
+
const newPerPage =
|
|
287
|
+
newParams.per_page !== undefined
|
|
288
|
+
? Number(newParams.per_page)
|
|
289
|
+
: pagination.perPage;
|
|
290
|
+
|
|
291
|
+
setPagination({ page: newPage, perPage: newPerPage });
|
|
292
|
+
},
|
|
293
|
+
[sortBy, pagination, setSortBy, setPagination]
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
const commitSearch = val => {
|
|
297
|
+
setSubmitError(null);
|
|
298
|
+
setSearchValue(val);
|
|
299
|
+
setPagination(prev => ({ ...prev, page: 1 }));
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
const handleFixSelected = () => {
|
|
303
|
+
if (areAllRowsSelected() || exclusionSet.size > 0) {
|
|
304
|
+
setSubmitError(null);
|
|
305
|
+
setIsSubmitting(true);
|
|
306
|
+
|
|
307
|
+
dispatch(
|
|
308
|
+
APIActions.post({
|
|
309
|
+
key: `BULK_REMEDIATE_${reportId}`,
|
|
310
|
+
url: foremanUrl(
|
|
311
|
+
`/api/v2/preupgrade_reports/${reportId}/preupgrade_report_entries/bulk_remediate`
|
|
312
|
+
),
|
|
313
|
+
params: {
|
|
314
|
+
search: searchValue,
|
|
315
|
+
excluded_ids: Array.from(exclusionSet),
|
|
316
|
+
},
|
|
317
|
+
handleSuccess: response => {
|
|
318
|
+
const result = response.data || response;
|
|
319
|
+
if (result?.id) {
|
|
320
|
+
window.location.assign(
|
|
321
|
+
foremanUrl(`/job_invocations/${result.id}`)
|
|
322
|
+
);
|
|
323
|
+
} else {
|
|
324
|
+
setIsSubmitting(false);
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
handleError: err => {
|
|
328
|
+
setSubmitError(err);
|
|
329
|
+
setIsSubmitting(false);
|
|
330
|
+
},
|
|
331
|
+
})
|
|
332
|
+
);
|
|
333
|
+
} else {
|
|
334
|
+
if (selectedIds.length === 0) return;
|
|
335
|
+
|
|
336
|
+
const hostIds =
|
|
337
|
+
hostIdsForSelected.length > 0
|
|
338
|
+
? hostIdsForSelected
|
|
339
|
+
: [globalHostId].filter(Boolean);
|
|
340
|
+
|
|
341
|
+
submitJobInvocation(
|
|
342
|
+
dispatch,
|
|
343
|
+
setSubmitError,
|
|
344
|
+
'leapp_remediation_plan',
|
|
345
|
+
hostIds,
|
|
346
|
+
selectedIds.join(','),
|
|
347
|
+
setIsSubmitting
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const handleRunUpgrade = () => {
|
|
353
|
+
const targetHostIds = globalHostId ? [globalHostId] : allHostIds;
|
|
354
|
+
submitJobInvocation(
|
|
355
|
+
dispatch,
|
|
356
|
+
setSubmitError,
|
|
357
|
+
'leapp_upgrade',
|
|
358
|
+
targetHostIds,
|
|
359
|
+
null,
|
|
360
|
+
setIsSubmitting
|
|
361
|
+
);
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
const [columnKeys, keysToColumnNames] = useMemo(
|
|
365
|
+
() => getColumnHelpers(columns),
|
|
366
|
+
[columns]
|
|
296
367
|
);
|
|
297
368
|
|
|
298
369
|
if (!isLeappJob) return null;
|
|
299
370
|
|
|
371
|
+
const hasAnySelection =
|
|
372
|
+
areAllRowsSelected() || exclusionSet.size > 0 || selectedIds.length > 0;
|
|
373
|
+
|
|
300
374
|
const isFixSelectedDisabled =
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
375
|
+
status === STATUS.PENDING ||
|
|
376
|
+
isSubmitting ||
|
|
377
|
+
!hasAnySelection ||
|
|
378
|
+
// When using select-all, check if any fixable entries exist on current page
|
|
379
|
+
(areAllRowsSelected() && pagedFixableEntries.length === 0);
|
|
380
|
+
|
|
381
|
+
const isRunUpgradeDisabled =
|
|
382
|
+
status === STATUS.PENDING ||
|
|
383
|
+
isSubmitting ||
|
|
384
|
+
(!globalHostId && allHostIds.length === 0);
|
|
385
|
+
|
|
386
|
+
const combinedErrorMessage =
|
|
387
|
+
(status === STATUS.ERROR && error?.message ? error.message : null) ||
|
|
388
|
+
submitError?.message ||
|
|
389
|
+
submitError?.error;
|
|
304
390
|
|
|
305
391
|
return (
|
|
306
392
|
<ExpandableSection
|
|
393
|
+
className="leapp-report-section"
|
|
307
394
|
isExpanded={isReportExpanded}
|
|
308
|
-
onToggle={(
|
|
395
|
+
onToggle={(_e, val) => setIsReportExpanded(val)}
|
|
309
396
|
toggleText={__('Leapp preupgrade report')}
|
|
310
397
|
>
|
|
311
|
-
|
|
312
|
-
<
|
|
313
|
-
<
|
|
314
|
-
|
|
315
|
-
|
|
398
|
+
<Toolbar ouiaId="leapp-report-toolbar">
|
|
399
|
+
<ToolbarContent>
|
|
400
|
+
<ToolbarGroup
|
|
401
|
+
variant="filter-group"
|
|
402
|
+
className="leapp-toolbar-filter-group"
|
|
403
|
+
>
|
|
404
|
+
{hasData && (
|
|
405
|
+
<ToolbarItem spacer={{ default: 'spacerNone' }}>
|
|
316
406
|
<SelectAllCheckbox
|
|
317
407
|
selectAll={selectAll}
|
|
318
408
|
selectPage={selectPage}
|
|
319
409
|
selectNone={selectNone}
|
|
320
|
-
selectedCount={
|
|
410
|
+
selectedCount={selectedCount}
|
|
321
411
|
pageRowCount={pagedFixableEntries.length}
|
|
322
|
-
totalCount={
|
|
412
|
+
totalCount={fixableCount}
|
|
323
413
|
areAllRowsOnPageSelected={areAllPageFixableSelected}
|
|
324
|
-
areAllRowsSelected={
|
|
414
|
+
areAllRowsSelected={areAllRowsSelected()}
|
|
325
415
|
/>
|
|
326
416
|
</ToolbarItem>
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
submitJobInvocation(
|
|
338
|
-
dispatch,
|
|
339
|
-
setError,
|
|
340
|
-
'leapp_remediation_plan',
|
|
341
|
-
hostIdsForSelected,
|
|
342
|
-
selectedIds.join(',')
|
|
343
|
-
)
|
|
344
|
-
}
|
|
345
|
-
ouiaId="fix-selected-button"
|
|
346
|
-
>
|
|
347
|
-
{__('Fix Selected')}
|
|
348
|
-
</Button>
|
|
349
|
-
</ToolbarItem>
|
|
350
|
-
<ToolbarItem>
|
|
351
|
-
<Button
|
|
352
|
-
variant="primary"
|
|
353
|
-
isDisabled={allHostIds.length === 0}
|
|
354
|
-
onClick={() =>
|
|
355
|
-
submitJobInvocation(
|
|
356
|
-
dispatch,
|
|
357
|
-
setError,
|
|
358
|
-
'leapp_upgrade',
|
|
359
|
-
allHostIds
|
|
360
|
-
)
|
|
361
|
-
}
|
|
362
|
-
ouiaId="run-upgrade-button"
|
|
363
|
-
>
|
|
364
|
-
{__('Run Upgrade')}
|
|
365
|
-
</Button>
|
|
417
|
+
)}
|
|
418
|
+
|
|
419
|
+
{reportId && searchProps && (
|
|
420
|
+
<ToolbarItem className="leapp-searchbar-item">
|
|
421
|
+
<SearchBar
|
|
422
|
+
data={searchProps}
|
|
423
|
+
searchQuery={searchValue}
|
|
424
|
+
onSearch={commitSearch}
|
|
425
|
+
bookmarks={searchProps.bookmarks}
|
|
426
|
+
/>
|
|
366
427
|
</ToolbarItem>
|
|
367
|
-
|
|
368
|
-
</
|
|
369
|
-
|
|
370
|
-
|
|
428
|
+
)}
|
|
429
|
+
</ToolbarGroup>
|
|
430
|
+
|
|
431
|
+
<ToolbarGroup
|
|
432
|
+
align={{ default: 'alignRight' }}
|
|
433
|
+
variant="button-group"
|
|
434
|
+
>
|
|
435
|
+
<ToolbarItem>
|
|
436
|
+
<Button
|
|
437
|
+
variant="secondary"
|
|
438
|
+
isDisabled={isFixSelectedDisabled}
|
|
439
|
+
onClick={handleFixSelected}
|
|
440
|
+
ouiaId="fix-selected-button"
|
|
441
|
+
isLoading={isSubmitting}
|
|
442
|
+
>
|
|
443
|
+
{__('Fix Selected')}
|
|
444
|
+
</Button>
|
|
445
|
+
</ToolbarItem>
|
|
446
|
+
<ToolbarItem>
|
|
447
|
+
<Button
|
|
448
|
+
variant="primary"
|
|
449
|
+
isDisabled={isRunUpgradeDisabled}
|
|
450
|
+
onClick={handleRunUpgrade}
|
|
451
|
+
ouiaId="run-upgrade-button"
|
|
452
|
+
isLoading={isSubmitting}
|
|
453
|
+
>
|
|
454
|
+
{__('Run Upgrade')}
|
|
455
|
+
</Button>
|
|
456
|
+
</ToolbarItem>
|
|
457
|
+
</ToolbarGroup>
|
|
458
|
+
</ToolbarContent>
|
|
459
|
+
</Toolbar>
|
|
371
460
|
|
|
372
461
|
<Table
|
|
373
462
|
ouiaId="leapp-report-table"
|
|
@@ -375,31 +464,38 @@ const PreupgradeReportsTable = ({ data = {} }) => {
|
|
|
375
464
|
isEmbedded
|
|
376
465
|
params={{
|
|
377
466
|
page: pagination.page,
|
|
378
|
-
|
|
379
|
-
|
|
467
|
+
per_page: pagination.perPage,
|
|
468
|
+
search: searchValue,
|
|
469
|
+
order: sortBy.index
|
|
470
|
+
? `${sortBy.index} ${sortBy.direction.toUpperCase()}`
|
|
471
|
+
: '',
|
|
380
472
|
}}
|
|
381
|
-
results={
|
|
382
|
-
itemCount={
|
|
473
|
+
results={rows}
|
|
474
|
+
itemCount={totalCount}
|
|
383
475
|
url=""
|
|
384
476
|
isPending={status === STATUS.PENDING}
|
|
385
|
-
errorMessage={
|
|
386
|
-
status === STATUS.ERROR && error?.message ? error.message : null
|
|
387
|
-
}
|
|
477
|
+
errorMessage={combinedErrorMessage}
|
|
388
478
|
showCheckboxes
|
|
389
479
|
refreshData={() => {}}
|
|
390
480
|
isDeleteable={false}
|
|
391
|
-
emptyMessage={
|
|
481
|
+
emptyMessage={
|
|
482
|
+
searchValue
|
|
483
|
+
? __('No results found for your search.')
|
|
484
|
+
: __('The preupgrade report shows no issues.')
|
|
485
|
+
}
|
|
392
486
|
setParams={handleParamsChange}
|
|
393
487
|
childrenOutsideTbody
|
|
394
488
|
onExpandAll={onExpandAll}
|
|
395
489
|
areAllRowsExpanded={!areAllRowsExpanded}
|
|
396
490
|
>
|
|
397
|
-
{
|
|
491
|
+
{rows.map((entry, rowIndex) => {
|
|
492
|
+
const rowKey = entry.id
|
|
493
|
+
? `entry-${entry.id}`
|
|
494
|
+
: `entry-row-${rowIndex}`;
|
|
398
495
|
const isRowExpanded = expandedRowIds.has(entry.id);
|
|
399
|
-
|
|
400
496
|
return (
|
|
401
497
|
<Tbody
|
|
402
|
-
key={
|
|
498
|
+
key={rowKey}
|
|
403
499
|
isExpanded={isRowExpanded}
|
|
404
500
|
className={isRowExpanded ? 'leapp-expanded-tbody' : ''}
|
|
405
501
|
>
|
|
@@ -408,7 +504,7 @@ const PreupgradeReportsTable = ({ data = {} }) => {
|
|
|
408
504
|
expand={{
|
|
409
505
|
rowIndex,
|
|
410
506
|
isExpanded: isRowExpanded,
|
|
411
|
-
onToggle: (
|
|
507
|
+
onToggle: (_e, _idx, isOpen) =>
|
|
412
508
|
toggleRowExpansion(entry.id, isOpen),
|
|
413
509
|
}}
|
|
414
510
|
/>
|
|
@@ -419,7 +515,10 @@ const PreupgradeReportsTable = ({ data = {} }) => {
|
|
|
419
515
|
isSelectable={isRowFixable}
|
|
420
516
|
/>
|
|
421
517
|
{columnKeys.map(key => (
|
|
422
|
-
<Td
|
|
518
|
+
<Td
|
|
519
|
+
key={`${rowKey}-col-${key}`}
|
|
520
|
+
dataLabel={keysToColumnNames[key]}
|
|
521
|
+
>
|
|
423
522
|
{columns[key].wrapper
|
|
424
523
|
? columns[key].wrapper(entry)
|
|
425
524
|
: entry[key]}
|