@rh-support/troubleshoot 2.3.0-alpha.0 → 2.4.5-beta.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.
- package/lib/esm/components/AccountInfo/OwnerSelector.d.ts.map +1 -1
- package/lib/esm/components/AccountInfo/OwnerSelector.js +1 -1
- package/lib/esm/components/CaseInformation/Description.d.ts.map +1 -1
- package/lib/esm/components/CaseInformation/Description.js +20 -16
- package/lib/esm/components/Cve/CveItem.d.ts +8 -0
- package/lib/esm/components/Cve/CveItem.d.ts.map +1 -0
- package/lib/esm/components/Cve/CveItem.js +86 -0
- package/lib/esm/components/Cve/CveModal.d.ts +3 -0
- package/lib/esm/components/Cve/CveModal.d.ts.map +1 -0
- package/lib/esm/components/Cve/CveModal.js +42 -0
- package/lib/esm/components/Cve/CvePanel.d.ts +7 -0
- package/lib/esm/components/Cve/CvePanel.d.ts.map +1 -0
- package/lib/esm/components/Cve/CvePanel.js +23 -0
- package/lib/esm/components/Cve/CveSidebar.d.ts +3 -0
- package/lib/esm/components/Cve/CveSidebar.d.ts.map +1 -0
- package/lib/esm/components/Cve/CveSidebar.js +24 -0
- package/lib/esm/components/OpenCase/OpenCase.d.ts +3 -0
- package/lib/esm/components/OpenCase/OpenCase.d.ts.map +1 -1
- package/lib/esm/components/OpenCase/OpenCase.js +8 -0
- package/lib/esm/components/ProductSelector/AllProductsSelector.d.ts +3 -0
- package/lib/esm/components/ProductSelector/AllProductsSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/AllProductsSelector.js +29 -21
- package/lib/esm/components/ProductSelector/NewProductDropdownSelector.d.ts +1 -0
- package/lib/esm/components/ProductSelector/NewProductDropdownSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/NewProductDropdownSelector.js +2 -2
- package/lib/esm/components/ProductSelector/NewProductVersionSelector.js +1 -1
- package/lib/esm/components/ProductSelector/ProductSelector.d.ts +4 -2
- package/lib/esm/components/ProductSelector/ProductSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/ProductSelector.js +12 -7
- package/lib/esm/components/ProductSelector/ProductVersionDropdownSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/ProductVersionDropdownSelector.js +1 -1
- package/lib/esm/components/Recommendations/AsideResults.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/AsideResults.js +2 -2
- package/lib/esm/components/Recommendations/EARules/EARuleWidget.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/EARules/EARuleWidget.js +5 -6
- package/lib/esm/components/Recommendations/Recommendations.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/Recommendations.js +54 -15
- package/lib/esm/components/Recommendations/RecommendationsLoader.d.ts +3 -0
- package/lib/esm/components/Recommendations/RecommendationsLoader.d.ts.map +1 -0
- package/lib/esm/components/Recommendations/RecommendationsLoader.js +11 -0
- package/lib/esm/components/Review/Review.d.ts.map +1 -1
- package/lib/esm/components/Review/Review.js +1 -1
- package/lib/esm/components/SessionRestore/SessionRestore.js +1 -1
- package/lib/esm/components/shared/useIsSectionValid.d.ts.map +1 -1
- package/lib/esm/components/shared/useIsSectionValid.js +14 -7
- package/lib/esm/components/wizardLayout/WizardAside.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/WizardAside.js +11 -9
- package/lib/esm/components/wizardLayout/WizardNavigation.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/WizardNavigation.js +28 -22
- package/lib/esm/css/results.css +6 -0
- package/lib/esm/hooks/useFetchCVEData.d.ts +5 -0
- package/lib/esm/hooks/useFetchCVEData.d.ts.map +1 -0
- package/lib/esm/hooks/useFetchCVEData.js +133 -0
- package/lib/esm/hooks/useWizard.d.ts.map +1 -1
- package/lib/esm/hooks/useWizard.js +11 -3
- package/lib/esm/models/caseCreationWorkflows.d.ts +25 -0
- package/lib/esm/models/caseCreationWorkflows.d.ts.map +1 -0
- package/lib/esm/models/caseCreationWorkflows.js +1 -0
- package/lib/esm/reducers/CaseConstNTypes.d.ts +4 -0
- package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
- package/lib/esm/reducers/CaseConstNTypes.js +3 -0
- package/lib/esm/reducers/CaseReducer.d.ts +1 -1
- package/lib/esm/reducers/CaseReducer.d.ts.map +1 -1
- package/lib/esm/reducers/CaseReducer.js +13 -9
- package/lib/esm/reducers/RouteConstNTypes.d.ts +0 -1
- package/lib/esm/reducers/RouteConstNTypes.d.ts.map +1 -1
- package/lib/esm/reducers/RouteConstNTypes.js +0 -1
- package/lib/esm/reducers/SessionRestoreReducer.d.ts +1 -1
- package/lib/esm/reducers/SessionRestoreReducer.d.ts.map +1 -1
- package/lib/esm/reducers/SessionRestoreReducer.js +15 -122
- package/lib/esm/scss/_main.scss +19 -0
- package/lib/esm/utils/caseUtils.d.ts +6 -0
- package/lib/esm/utils/caseUtils.d.ts.map +1 -1
- package/lib/esm/utils/caseUtils.js +15 -0
- package/package.json +9 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EARuleWidget.d.ts","sourceRoot":"","sources":["../../../../../src/components/Recommendations/EARules/EARuleWidget.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAWrD,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"EARuleWidget.d.ts","sourceRoot":"","sources":["../../../../../src/components/Recommendations/EARules/EARuleWidget.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAWrD,wBAAgB,YAAY,sBAmD3B"}
|
|
@@ -14,11 +14,10 @@ export function EARuleWidget() {
|
|
|
14
14
|
const { rulesState: { isEARuleWidgetVisible, EARules }, } = useContext(RulesStateContext);
|
|
15
15
|
const { sessionRestore: { activeSessionId, sessionResourceTracking }, } = useContext(SessionRestoreStateContext);
|
|
16
16
|
const sessionRestoreDispatch = useContext(SessionRestoreDispatchContext);
|
|
17
|
-
const { product, version, summary
|
|
17
|
+
const { product, version, summary } = useCaseSelector((state) => ({
|
|
18
18
|
product: state.caseDetails.product,
|
|
19
19
|
version: state.caseDetails.version,
|
|
20
20
|
summary: state.caseDetails.summary,
|
|
21
|
-
issue: state.caseDetails.issue,
|
|
22
21
|
}), isEqual);
|
|
23
22
|
const validEARules = filter(EARules.rules, (r) => r.visible && r.rule_sub_type !== 'attachment');
|
|
24
23
|
useEffect(() => {
|
|
@@ -28,10 +27,10 @@ export function EARuleWidget() {
|
|
|
28
27
|
if (visibleValidEARules &&
|
|
29
28
|
differenceBy([visibleValidEARules === null || visibleValidEARules === void 0 ? void 0 : visibleValidEARules.rule_id], presentedIds).length > 0 &&
|
|
30
29
|
!isEmpty(activeSessionId)) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.EDMOUND_ABOTT, [
|
|
31
|
+
getSessResFromRules(visibleValidEARules.cta, SessionResourceVisibility.PRESENTED, 1, visibleValidEARules.rule_id),
|
|
32
|
+
], JSON.stringify({ product, version, summary }) // To trigger EA rules, we don't pass KT questions
|
|
33
|
+
);
|
|
35
34
|
}
|
|
36
35
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
36
|
}, [validEARules, activeSessionId]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Recommendations.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/Recommendations.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Recommendations.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/Recommendations.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AAelE,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAYpF,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,uBAAuB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACzE,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,aAAa,EAAE,GAAG,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,MAAM,qBA0WpD"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { pcm } from '@cee-eng/hydrajs';
|
|
2
|
-
import { Label, Pagination, PaginationVariant } from '@patternfly/react-core';
|
|
2
|
+
import { Label, Pagination, PaginationVariant, Popover, Spinner } from '@patternfly/react-core';
|
|
3
|
+
import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
|
|
4
|
+
import StarIcon from '@patternfly/react-icons/dist/js/icons/star-icon';
|
|
3
5
|
import { LoadingDots, useDebounce, usePrevious } from '@rh-support/components';
|
|
4
6
|
import { useGlobalStateContext } from '@rh-support/react-context';
|
|
5
7
|
import { computeRecommendationAbstract, computeRecommendationTitle, dtmTrackEventCaseStartStopped, formatDate, } from '@rh-support/utils';
|
|
@@ -20,17 +22,19 @@ import { fetchRecommendations, fetchWatsonXRecommendations, RecommendationsConst
|
|
|
20
22
|
import { AppRouteSections } from '../../reducers/RouteConstNTypes';
|
|
21
23
|
import { createOrUpdateSessionResources, getSessResFromRec, getSessResFromRecs, } from '../../reducers/SessionRestoreReducer';
|
|
22
24
|
import RouteUtils from '../../utils/routeUtils';
|
|
25
|
+
import { RecommendationsLoader } from './RecommendationsLoader';
|
|
23
26
|
import { WatsonxAiIcon } from './WatsonxAiIcon';
|
|
24
27
|
const { SessionResourceSource, SessionResourceVisibility } = pcm.preCase.session;
|
|
25
28
|
export default function Recommendations(props) {
|
|
26
29
|
var _a, _b, _c;
|
|
27
|
-
const { product, version, environment, summary, caseResourceLinks, issue } = useCaseSelector((state) => ({
|
|
30
|
+
const { product, version, environment, summary, caseResourceLinks, issue, enableGetSupportProductVersion } = useCaseSelector((state) => ({
|
|
28
31
|
product: state.caseDetails.product,
|
|
29
32
|
version: state.caseDetails.version,
|
|
30
33
|
environment: state.caseDetails.environment,
|
|
31
34
|
summary: state.caseDetails.summary,
|
|
32
35
|
issue: state.caseDetails.issue,
|
|
33
36
|
caseResourceLinks: state.caseDetails.caseResourceLinks,
|
|
37
|
+
enableGetSupportProductVersion: state.enableGetSupportProductVersion,
|
|
34
38
|
}), isEqual);
|
|
35
39
|
const caseDispatch = useCaseDispatch();
|
|
36
40
|
// Use Case Number
|
|
@@ -59,6 +63,9 @@ export default function Recommendations(props) {
|
|
|
59
63
|
// currently due to the debounce we use after the page load leads to some delay in the disbaling of next button
|
|
60
64
|
// since the state of the next button depends on the loading rec flag so we force the flag to be true every time the
|
|
61
65
|
// rec section is rendered for the first time except the case when we won't make a new search since there was no change in the rec payload.
|
|
66
|
+
if (activeSection !== AppRouteSections.SUMMARIZE || !summary || isRecSearchPayloadSame) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
62
69
|
!isRecSearchPayloadSame &&
|
|
63
70
|
recommendationDispatch({
|
|
64
71
|
type: RecommendationsConstants.setIsLoadingRecommendations,
|
|
@@ -85,7 +92,7 @@ export default function Recommendations(props) {
|
|
|
85
92
|
// recreate a new AbortController for each call
|
|
86
93
|
let controller = new AbortController();
|
|
87
94
|
abortControllerRef.current = controller;
|
|
88
|
-
if (!isEmpty(issue)) {
|
|
95
|
+
if (!isEmpty(issue) || !isEmpty(summary)) {
|
|
89
96
|
!loggedInUsersAccount.data.secureSupport
|
|
90
97
|
? fetchWatsonXRecommendations(recommendationDispatch, payload, MAXROW, recPageSize, 0, true, queryFilters, controller.signal)
|
|
91
98
|
: fetchRecommendations(recommendationDispatch, payload, MAXROW, recPageSize, 0, true, caseNumber, isSecureSupportAccount, queryFilters, controller.signal);
|
|
@@ -106,9 +113,9 @@ export default function Recommendations(props) {
|
|
|
106
113
|
recommendationState.insightsKcsIds,
|
|
107
114
|
], 1000);
|
|
108
115
|
useEffect(() => {
|
|
109
|
-
props.userSeenRecommendations && props.userSeenRecommendations(!recommendationState.isLoadingRecommendations);
|
|
116
|
+
props.userSeenRecommendations && props.userSeenRecommendations(!recommendationState.isLoadingRecommendations); //reset userSeenRecommendations when recommendationState changes
|
|
110
117
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
111
|
-
}, [recommendationState]);
|
|
118
|
+
}, [recommendationState.numFound]);
|
|
112
119
|
useEffect(() => {
|
|
113
120
|
if (recommendationState.isLoadingRecommendations)
|
|
114
121
|
return;
|
|
@@ -120,7 +127,7 @@ export default function Recommendations(props) {
|
|
|
120
127
|
if (newRecommendations.length > 0) {
|
|
121
128
|
setCaseRecommendations(caseDispatch, recommendationState.visibleDocs, caseResourceLinks);
|
|
122
129
|
}
|
|
123
|
-
createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS, getSessResFromRecs(recommendationState.visibleDocs, SessionResourceVisibility.PRESENTED, pageSize || DEFAULTPAGESIZE, recommendationState.currentPage || 1), JSON.stringify(payload));
|
|
130
|
+
createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS, getSessResFromRecs(recommendationState.visibleDocs, SessionResourceVisibility.PRESENTED, pageSize || DEFAULTPAGESIZE, recommendationState.currentPage || 1), typeof payload === 'string' ? payload : JSON.stringify(payload));
|
|
124
131
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
125
132
|
}, [caseDispatch, recommendationState.visibleDocs, activeSessionId]);
|
|
126
133
|
useEffect(() => {
|
|
@@ -147,29 +154,61 @@ export default function Recommendations(props) {
|
|
|
147
154
|
const onResourceClick = (doc, index) => (event) => {
|
|
148
155
|
createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS, [
|
|
149
156
|
getSessResFromRec(doc, SessionResourceVisibility.VISITED, index + 1 + (pageSize || DEFAULTPAGESIZE) * ((recommendationState.currentPage || 1) - 1)),
|
|
150
|
-
], JSON.stringify(payload));
|
|
157
|
+
], typeof payload === 'string' ? payload : JSON.stringify(payload));
|
|
151
158
|
dtmTrackEventCaseStartStopped('recommendation click', caseNumber, `${product}|${version}`);
|
|
152
159
|
};
|
|
160
|
+
const infoPopover = (React.createElement(Popover, { triggerAction: "hover", "aria-label": "Hoverable popover", headerContent: React.createElement("div", null,
|
|
161
|
+
React.createElement(Trans, null, "Powered by Openshift AI")), bodyContent: React.createElement("div", null,
|
|
162
|
+
React.createElement(Trans, null, "These articles have been selected based on the information provided."),
|
|
163
|
+
React.createElement("br", null),
|
|
164
|
+
React.createElement("a", { href: "#" }, "Learn more")) },
|
|
165
|
+
React.createElement(InfoCircleIcon, { color: "white" })));
|
|
166
|
+
function getRankPercentage(decimal) {
|
|
167
|
+
return Math.round(decimal * 100);
|
|
168
|
+
}
|
|
169
|
+
const computeLabel = (doc) => {
|
|
170
|
+
const percentage = getRankPercentage(doc.rerank_score);
|
|
171
|
+
return (React.createElement(React.Fragment, null,
|
|
172
|
+
percentage > 80 && (React.createElement(Label, { color: "green", className: "match-label", icon: React.createElement(StarIcon, null) }, "Best Match")),
|
|
173
|
+
React.createElement(Label, { className: "match-label", color: "purple" },
|
|
174
|
+
percentage,
|
|
175
|
+
"% Match")));
|
|
176
|
+
};
|
|
153
177
|
return (React.createElement(React.Fragment, null,
|
|
154
|
-
React.createElement(LoadingDots, { className: "recommendation-loading-dots", show: recommendationState.isLoadingRecommendations && !isEmpty(summary) && !isEmpty(issue) }),
|
|
155
|
-
React.createElement("div", { className: "recommendation-list
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
178
|
+
!enableGetSupportProductVersion && (React.createElement(LoadingDots, { className: "recommendation-loading-dots", show: recommendationState.isLoadingRecommendations && !isEmpty(summary) && !isEmpty(issue) })),
|
|
179
|
+
React.createElement("div", { className: "recommendation-list", ref: props.resultsRowRef },
|
|
180
|
+
enableGetSupportProductVersion
|
|
181
|
+
? (recommendationState.visibleDocs.length !== 0 ||
|
|
182
|
+
recommendationState.isLoadingRecommendations) && (React.createElement(Label, { id: "DeepPurpleColorAILabel", className: "pf-v5-u-mb-md" }, recommendationState.isLoadingRecommendations ? (React.createElement(React.Fragment, null,
|
|
183
|
+
React.createElement(Spinner, { size: "sm", className: "pf-v5-u-mr-xs" }),
|
|
184
|
+
' ',
|
|
185
|
+
React.createElement(Trans, null, "Recommending articles using OpenShift AI"),
|
|
186
|
+
' ',
|
|
187
|
+
React.createElement(InfoCircleIcon, { color: "white" }))) : (React.createElement(React.Fragment, null,
|
|
188
|
+
React.createElement(WatsonxAiIcon, { fillColor: "#FFFFFF", className: "pf-v5-u-mr-xs" }),
|
|
189
|
+
' ',
|
|
190
|
+
React.createElement(Trans, null, "Articles recommended by OpenShift AI"),
|
|
191
|
+
" ",
|
|
192
|
+
infoPopover))))
|
|
193
|
+
: recommendationState.visibleDocs.length !== 0 && (React.createElement(Label, { color: "purple", className: "pf-v5-u-mb-md" },
|
|
194
|
+
React.createElement(WatsonxAiIcon, { fillColor: "#6753ac", className: "pf-v5-u-mr-xs" }),
|
|
195
|
+
React.createElement(Trans, null, "Live search results powered by OpenShift AI"))),
|
|
196
|
+
enableGetSupportProductVersion && recommendationState.isLoadingRecommendations ? ( // as much as it pains me to add these <br /> the pf docs has it this way
|
|
197
|
+
React.createElement(RecommendationsLoader, null)) : (React.createElement("ul", { className: "list-flat" }, map(recommendationState.visibleDocs, (doc, i) => {
|
|
160
198
|
var _a, _b;
|
|
161
199
|
return (React.createElement("li", { className: "result", key: doc.id },
|
|
162
200
|
React.createElement("header", { className: "result-header" },
|
|
163
201
|
React.createElement("a", { href: `${doc.view_uri}?${RouteUtils.getSEResourceQueryParams(activeSessionId, (_b = (_a = sessionResourceTracking[SessionResourceSource.RECOMMENDATIONS]) === null || _a === void 0 ? void 0 : _a.resourceOriginId) !== null && _b !== void 0 ? _b : '', SessionResourceSource.RECOMMENDATIONS)}`, className: "se-recommended ts-result", "data-tracking-id": `se-recommended-main-recommendations-${i}`, rel: "noopener noreferrer", target: "_blank", onClick: onResourceClick(doc, i), dangerouslySetInnerHTML: computeRecommendationTitle(doc) }),
|
|
164
202
|
React.createElement("div", { className: "header-meta" },
|
|
203
|
+
enableGetSupportProductVersion && computeLabel(doc),
|
|
165
204
|
doc.kcsState === 'verified' && (React.createElement(React.Fragment, null,
|
|
166
|
-
React.createElement("span", { className: "status-verified" }, "verified"),
|
|
205
|
+
React.createElement("span", { className: "status-verified pf-v5-u-font-weight-bold pf-v5-u-success-color-100" }, "verified"),
|
|
167
206
|
React.createElement("span", { className: "list-separator" }, "\u2013"))),
|
|
168
207
|
React.createElement("span", { className: "meta" }, doc.documentKind),
|
|
169
208
|
React.createElement("span", { className: "list-separator" }, "\u2013"),
|
|
170
209
|
React.createElement("time", { className: "moment_date meta", title: doc.lastModifiedDate.toString() }, formatDate(doc.lastModifiedDate)))),
|
|
171
210
|
React.createElement("p", { className: "result-body", dangerouslySetInnerHTML: computeRecommendationAbstract(doc, 300) })));
|
|
172
|
-
})),
|
|
211
|
+
}))),
|
|
173
212
|
recommendationState.numFound !== 0 && recommendationState.numFound > DEFAULTPAGESIZE && (React.createElement("div", { className: "pagination-footer" },
|
|
174
213
|
React.createElement(Pagination, { className: "push-top", itemCount: (_c = (_b = recommendationState.allDocs) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0, perPage: recPageSize, page: recommendationState.currentPage, variant: PaginationVariant.bottom, onSetPage: pageChanged, dropDirection: "up", onPerPageSelect: onPageSizeChanged })))),
|
|
175
214
|
recommendationState.visibleDocs.length === 0 &&
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecommendationsLoader.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/RecommendationsLoader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,eAAO,MAAM,qBAAqB,yBAejC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Skeleton } from '@patternfly/react-core';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export const RecommendationsLoader = () => {
|
|
4
|
+
return (React.createElement("div", { className: "pf-v5-u-mt-md" }, [...Array(5)].map((_, i) => (React.createElement(React.Fragment, { key: `recommendation-loading-${i}` },
|
|
5
|
+
React.createElement(Skeleton, { height: "20px", width: "100%" }),
|
|
6
|
+
React.createElement("br", null),
|
|
7
|
+
React.createElement(Skeleton, { height: "45px", width: "100%" }),
|
|
8
|
+
React.createElement("br", null),
|
|
9
|
+
React.createElement("br", null),
|
|
10
|
+
React.createElement("br", null))))));
|
|
11
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Review.d.ts","sourceRoot":"","sources":["../../../../src/components/Review/Review.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAsBlE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;CACpD;AACD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"Review.d.ts","sourceRoot":"","sources":["../../../../src/components/Review/Review.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAsBlE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;CACpD;AACD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,MAAM,qBA8E3C"}
|
|
@@ -48,7 +48,7 @@ export default function Review(props) {
|
|
|
48
48
|
React.createElement("form", { className: "review-form card card-light push-bottom" },
|
|
49
49
|
React.createElement(AccountSelector, null),
|
|
50
50
|
React.createElement(OwnerSelector, null),
|
|
51
|
-
React.createElement(AllProductsSelector, { routeProps: props.routeProps, loadTCOnChange: true, showTCAfterButtonClicked: true, checkEntitledProduct: true }),
|
|
51
|
+
React.createElement(AllProductsSelector, { routeProps: props.routeProps, loadTCOnChange: true, showTCAfterButtonClicked: true, checkEntitledProduct: true, isOnReviewPage: true }),
|
|
52
52
|
React.createElement(OpenShiftClusterId, null),
|
|
53
53
|
React.createElement(Hostname, null),
|
|
54
54
|
React.createElement(KtQuestions, { inlineEditable: true, hideSaveCancel: true }),
|
|
@@ -298,7 +298,7 @@ export function SessionRestore(props) {
|
|
|
298
298
|
], 1000);
|
|
299
299
|
if (!sessionRestoreCardSections.includes(activeSection))
|
|
300
300
|
return React.createElement(React.Fragment, null);
|
|
301
|
-
return (React.createElement(
|
|
301
|
+
return (React.createElement("div", { className: "pf-v5-u-mb-md pf-v5-u-mt-0" },
|
|
302
302
|
' ',
|
|
303
303
|
React.createElement(SessionRestoreCard, { onRestore: restoreSession, previousSessions: previousSessions, onCardDismiss: onSessionRestoreCardDismiss }),
|
|
304
304
|
React.createElement(RestoreLastSessionModal, { onRestore: restoreSession, errorSession: sessionRestore.sessionOfCaseCreationError })));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useIsSectionValid.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/useIsSectionValid.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAuB1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAInE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,gBAAgB;;;;;
|
|
1
|
+
{"version":3,"file":"useIsSectionValid.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/useIsSectionValid.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAuB1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAInE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,gBAAgB;;;;;EA+M9D"}
|
|
@@ -14,7 +14,7 @@ import { AppRouteSections } from '../../reducers/RouteConstNTypes';
|
|
|
14
14
|
import { AttachmentStateContext } from './fileUpload/reducer/AttachmentReducerContext';
|
|
15
15
|
export function useIsSectionValid(sectionName) {
|
|
16
16
|
var _a, _b;
|
|
17
|
-
const { caseState, caseType, product, version, contactSSOName, accountNumber, summary, hostname, contactInfo24x7, alternateId, selectedAccountDetails, issue, environment, timeFramesAndUrgency, periodicityOfIssue, } = useCaseSelector((state) => ({
|
|
17
|
+
const { caseState, caseType, product, version, contactSSOName, accountNumber, summary, hostname, contactInfo24x7, alternateId, selectedAccountDetails, issue, environment, timeFramesAndUrgency, periodicityOfIssue, enableGetSupportProductVersion, } = useCaseSelector((state) => ({
|
|
18
18
|
caseState: state,
|
|
19
19
|
caseType: state.caseDetails.caseType,
|
|
20
20
|
product: state.caseDetails.product,
|
|
@@ -30,6 +30,7 @@ export function useIsSectionValid(sectionName) {
|
|
|
30
30
|
environment: state.caseDetails.environment,
|
|
31
31
|
timeFramesAndUrgency: state.caseDetails.timeFramesAndUrgency,
|
|
32
32
|
periodicityOfIssue: state.caseDetails.periodicityOfIssue,
|
|
33
|
+
enableGetSupportProductVersion: state.enableGetSupportProductVersion,
|
|
33
34
|
}), isEqual);
|
|
34
35
|
const { globalMetadataState: { allProducts, loggedInUserJwtToken }, } = useContext(GlobalMetadataStateContext);
|
|
35
36
|
const { topContentState: { topContent }, } = useContext(TCStateContext);
|
|
@@ -49,22 +50,28 @@ export function useIsSectionValid(sectionName) {
|
|
|
49
50
|
return !hasUnallowedFiles && !hasOversizeFiles; // we want it false to trigger the error if its true
|
|
50
51
|
};
|
|
51
52
|
const isGetSupportSectionValidLocal = () => {
|
|
52
|
-
|
|
53
|
+
let isValid = !isEmpty(caseType) &&
|
|
53
54
|
!isEmpty(accountNumber) &&
|
|
54
55
|
!isEmpty(contactSSOName) &&
|
|
55
|
-
!selectedAccountDetails.data.subscriptionAbuse
|
|
56
|
+
!selectedAccountDetails.data.subscriptionAbuse;
|
|
57
|
+
if (enableGetSupportProductVersion) {
|
|
58
|
+
isValid = isValid && !isEmpty(product) && !isEmpty(version);
|
|
59
|
+
}
|
|
60
|
+
return isValid;
|
|
56
61
|
};
|
|
57
62
|
const isSummarizeSectionValid = () => {
|
|
58
|
-
|
|
59
|
-
!isEmpty(version) &&
|
|
60
|
-
!allProducts.isFetching &&
|
|
63
|
+
let isValid = !allProducts.isFetching &&
|
|
61
64
|
!allProducts.isError &&
|
|
62
65
|
!topContent.isFetching &&
|
|
63
66
|
!isEmpty(summary) &&
|
|
64
67
|
!isEmpty(issue) &&
|
|
65
68
|
!recommendationState.isLoadingRecommendations &&
|
|
66
69
|
(summary === null || summary === void 0 ? void 0 : summary.length) <= TITLE_SUMMARY_LENGTH_LIMIT &&
|
|
67
|
-
(issue === null || issue === void 0 ? void 0 : issue.length) <= ISSUE_SUMMARY_LENGTH_LIMIT
|
|
70
|
+
(issue === null || issue === void 0 ? void 0 : issue.length) <= ISSUE_SUMMARY_LENGTH_LIMIT;
|
|
71
|
+
if (!enableGetSupportProductVersion) {
|
|
72
|
+
isValid = isValid && !isEmpty(product) && !isEmpty(version);
|
|
73
|
+
}
|
|
74
|
+
return isValid;
|
|
68
75
|
};
|
|
69
76
|
const isCaseManagementSectionValid = () => {
|
|
70
77
|
const hasContactInfo24x7ValidLength = contactInfo24x7
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WizardAside.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardAside.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAGH,eAAe,
|
|
1
|
+
{"version":3,"file":"WizardAside.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardAside.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAGH,eAAe,EAIlB,MAAM,iCAAiC,CAAC;AASzC,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAGD,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,qBAwDjC;kBAxDQ,WAAW;;;AA0DpB,eAAe,WAAW,CAAC"}
|
|
@@ -5,21 +5,23 @@ import isUndefined from 'lodash/isUndefined';
|
|
|
5
5
|
import React, { useContext } from 'react';
|
|
6
6
|
import { useCaseSelector } from '../../context/CaseContext';
|
|
7
7
|
import { RouteContext } from '../../context/RouteContext';
|
|
8
|
-
import { AppRouteSections, hideFileUploadSidebarWidgetSections,
|
|
8
|
+
import { AppRouteSections, hideFileUploadSidebarWidgetSections, showSideBarClusterIdRuleWidgetSections, showSideBarEARuleWidgetSections, showSideBarFileRecommendationSections, } from '../../reducers/RouteConstNTypes';
|
|
9
9
|
import { FileDiag } from '../CaseInformation/FileDiag';
|
|
10
|
+
import { CveSidebar } from '../Cve/CveSidebar';
|
|
10
11
|
import { AsideResults } from '../Recommendations/AsideResults';
|
|
11
12
|
import ClusterRecommendations from '../Recommendations/ClusterRecommendations';
|
|
12
13
|
import { EARuleWidget } from '../Recommendations/EARules/EARuleWidget';
|
|
13
14
|
import InsightsResults from '../Recommendations/InsightsResults';
|
|
14
|
-
import { RecommendationInfoBox } from '../Recommendations/RecommendationInfoBox';
|
|
15
15
|
import { SessionRestore } from '../SessionRestore';
|
|
16
16
|
const defaultProps = {};
|
|
17
17
|
function WizardAside(props) {
|
|
18
18
|
const { routeState: { activeSection }, } = useContext(RouteContext);
|
|
19
19
|
const canAddAttachments = ability.can(resourceActions.PATCH, resources.CASE_CREATE, CaseListFields.ATTACHMENTS);
|
|
20
|
-
const { isCreatingCase, caseType } = useCaseSelector((state) => ({
|
|
20
|
+
const { isCreatingCase, caseType, isCveModalOpened, enableGetSupportProductVersion } = useCaseSelector((state) => ({
|
|
21
21
|
isCreatingCase: state.isCreatingCase,
|
|
22
22
|
caseType: state.caseDetails.caseType,
|
|
23
|
+
isCveModalOpened: state.isCveModalOpened,
|
|
24
|
+
enableGetSupportProductVersion: state.enableGetSupportProductVersion,
|
|
23
25
|
}), isEqual);
|
|
24
26
|
const isIdea = caseType === PreviousCaseTypes.FEATURE_ENHANCEMENT;
|
|
25
27
|
const canUseSessionManagement = ability.can(resourceActions.CREATE, resources.SESSION_TRACKING);
|
|
@@ -27,20 +29,20 @@ function WizardAside(props) {
|
|
|
27
29
|
!props.isAttachmentUploadModalOpen &&
|
|
28
30
|
!isUndefined(activeSection) &&
|
|
29
31
|
!hideFileUploadSidebarWidgetSections.includes(activeSection);
|
|
30
|
-
const
|
|
32
|
+
const canShowEARuleWidget = showSideBarEARuleWidgetSections.includes(activeSection);
|
|
31
33
|
const canShowClusterIdReportWidget = showSideBarClusterIdRuleWidgetSections.includes(activeSection);
|
|
32
34
|
const canShowFileRecommendationSectionsWidget = showSideBarFileRecommendationSections.includes(activeSection);
|
|
33
|
-
const canShowRecommendationTips = showRecommendationTipsSections.includes(activeSection) && !isIdea;
|
|
34
35
|
return (React.createElement("aside", null,
|
|
35
36
|
React.createElement("section", { className: "grid-aside-content" },
|
|
37
|
+
canUseSessionManagement && !isCreatingCase && activeSection !== AppRouteSections.SUBMIT_CASE && (React.createElement(SessionRestore, { routeProps: props.routeProps })),
|
|
36
38
|
canShowFileUploadWidget() && React.createElement(InsightsResults, null),
|
|
37
39
|
canShowFileUploadWidget() && React.createElement(FileDiag, { className: "pf-v5-u-mb-md" }),
|
|
38
|
-
|
|
40
|
+
activeSection === AppRouteSections.SUMMARIZE && !isCveModalOpened && React.createElement(CveSidebar, null),
|
|
41
|
+
activeSection === AppRouteSections.TROUBLESHOOT && React.createElement(CveSidebar, null),
|
|
42
|
+
enableGetSupportProductVersion && canShowEARuleWidget && React.createElement(EARuleWidget, null),
|
|
39
43
|
!(isIdea && activeSection === 'submit-case') && (React.createElement(AsideResults, { routeProps: props.routeProps, className: "pf-v5-u-mb-md pf-v5-u-mt-0" })),
|
|
40
44
|
canShowFileRecommendationSectionsWidget && React.createElement(InsightsResults, { isDisplayOnMain: true }),
|
|
41
|
-
React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v5-u-mb-md pf-v5-u-mt-0" })
|
|
42
|
-
canUseSessionManagement && !isCreatingCase && activeSection !== AppRouteSections.SUBMIT_CASE && (React.createElement(SessionRestore, { routeProps: props.routeProps })),
|
|
43
|
-
canShowRecommendationTips && React.createElement(RecommendationInfoBox, null))));
|
|
45
|
+
React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v5-u-mb-md pf-v5-u-mt-0" }))));
|
|
44
46
|
}
|
|
45
47
|
WizardAside.defaultProps = defaultProps;
|
|
46
48
|
export default WizardAside;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WizardNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardNavigation.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAAoB,eAAe,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAK3G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,EAAE,CAAC,gCAAgC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzE,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,0BAA0B,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5E,kCAAkC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACpF,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,gCAAgC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,oBAAoB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CACxE;AAGD,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"WizardNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardNavigation.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAAoB,eAAe,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAK3G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,EAAE,CAAC,gCAAgC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzE,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,0BAA0B,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5E,kCAAkC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACpF,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,gCAAgC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,oBAAoB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;CACxE;AAGD,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,qBA4PtC;kBA5PQ,gBAAgB;;;AA8PzB,eAAe,gBAAgB,CAAC"}
|
|
@@ -70,16 +70,30 @@ function WizardNavigation(props) {
|
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
const observer = new IntersectionObserver(([entry]) => {
|
|
73
|
-
if
|
|
74
|
-
|
|
73
|
+
// future debugging needs if resolution issue occurs
|
|
74
|
+
// console.log('Intersection status:', entry.isIntersecting);
|
|
75
|
+
// console.log('Intersection ratio:', entry.intersectionRatio);
|
|
76
|
+
// console.log({ hasUserScrolled });
|
|
77
|
+
const boundingRect = entry.boundingClientRect;
|
|
78
|
+
const isScrollingUp = boundingRect.top > 0;
|
|
79
|
+
const isAboveThreshold = entry.intersectionRatio >= 0.3;
|
|
80
|
+
isAboveThreshold && props.setUserCanNavigateToTroubleshoot(true);
|
|
81
|
+
isAboveThreshold && props.setUserSeenRecommendations(true);
|
|
82
|
+
// If scrolling up, always use the threshold check
|
|
83
|
+
if (isScrollingUp) {
|
|
84
|
+
setHasUserScrolled(isAboveThreshold);
|
|
85
|
+
props.setUserScrolledLabel(isAboveThreshold);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// If scrolling down and we hit the threshold, set to true
|
|
89
|
+
if (isAboveThreshold) {
|
|
75
90
|
props.setUserScrolledLabel(true);
|
|
76
|
-
|
|
77
|
-
props.userClickedNextonRecommendationsFn(true);
|
|
78
|
-
}
|
|
91
|
+
props.userClickedNextonRecommendationsFn && props.userClickedNextonRecommendationsFn(true);
|
|
79
92
|
}
|
|
80
93
|
}, {
|
|
81
94
|
root: null,
|
|
82
|
-
threshold: 0.
|
|
95
|
+
threshold: [0, 0.3], // Changing threshold value to have its effect on pagination when page size is more than 10.
|
|
96
|
+
rootMargin: '0px',
|
|
83
97
|
});
|
|
84
98
|
const resultsRowElement = props.resultsRowRef.current;
|
|
85
99
|
if (resultsRowElement) {
|
|
@@ -90,30 +104,22 @@ function WizardNavigation(props) {
|
|
|
90
104
|
observer.unobserve(resultsRowElement);
|
|
91
105
|
}
|
|
92
106
|
};
|
|
93
|
-
}, [recommendationState.numFound,
|
|
107
|
+
}, [recommendationState.numFound, hasUserScrolled, props]);
|
|
94
108
|
const onNext = () => {
|
|
95
109
|
var _a;
|
|
96
110
|
updateisNextBtnClickedToShowValidationError(dispatchToRouteReducer, true);
|
|
97
111
|
//handle the new changes for 13406:
|
|
98
112
|
if (props.activeStep.id === AppRouteSections.SUMMARIZE && recommendationState.numFound > 2) {
|
|
99
|
-
if (!
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
});
|
|
107
|
-
}
|
|
113
|
+
if (!hasUserScrolled) {
|
|
114
|
+
scrollIntoView(props.resultsRowRef, {
|
|
115
|
+
navBarRef,
|
|
116
|
+
timeout: 0,
|
|
117
|
+
onlyIfNotInViewport: true,
|
|
118
|
+
offset: 120,
|
|
119
|
+
});
|
|
108
120
|
props.userClickedNextonRecommendationsFn && props.userClickedNextonRecommendationsFn(true);
|
|
109
121
|
return;
|
|
110
122
|
}
|
|
111
|
-
else {
|
|
112
|
-
props.setUserCanNavigateToTroubleshoot(true);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
props.setUserCanNavigateToTroubleshoot(true);
|
|
117
123
|
}
|
|
118
124
|
const userCanNotOpenCase = props.activeStep.id === AppRouteSections.TROUBLESHOOT && canCreateCase.alert();
|
|
119
125
|
if (userCanNotOpenCase || !isSectionValidFn(props.activeStep.id))
|
package/lib/esm/css/results.css
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFetchCVEData.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFetchCVEData.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,0BAA0B,EAAkB,MAAM,iCAAiC,CAAC;AAI7F,wBAAgB,eAAe;;EA8H9B"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { search } from '@cee-eng/hydrajs';
|
|
11
|
+
import { useLRUCache } from '@rh-support/components';
|
|
12
|
+
import filter from 'lodash/filter';
|
|
13
|
+
import isArray from 'lodash/isArray';
|
|
14
|
+
import isEmpty from 'lodash/isEmpty';
|
|
15
|
+
import isEqual from 'lodash/isEqual';
|
|
16
|
+
import map from 'lodash/map';
|
|
17
|
+
import sortBy from 'lodash/sortBy';
|
|
18
|
+
import { useContext, useEffect, useState } from 'react';
|
|
19
|
+
import { useCaseDispatch, useCaseSelector } from '../context/CaseContext';
|
|
20
|
+
import { RecommendationStateContext } from '../context/RecommendationContext';
|
|
21
|
+
import { setCaseState } from '../reducers/CaseReducer';
|
|
22
|
+
import { findCVEsInString } from '../utils/caseUtils';
|
|
23
|
+
// custom hook for CVE workflow data .
|
|
24
|
+
export function useFetchCVEData() {
|
|
25
|
+
const caseDispatch = useCaseDispatch();
|
|
26
|
+
const { recommendationState } = useContext(RecommendationStateContext);
|
|
27
|
+
const [cveRecommendation, setCveRecommendation] = useState([]);
|
|
28
|
+
const { product, version, summary, description } = useCaseSelector((state) => ({
|
|
29
|
+
product: state.caseDetails.product,
|
|
30
|
+
version: state.caseDetails.version,
|
|
31
|
+
summary: state.caseDetails.summary,
|
|
32
|
+
description: state.caseDetails.description,
|
|
33
|
+
}), isEqual);
|
|
34
|
+
const { getFromCache, setInCache } = useLRUCache(50);
|
|
35
|
+
const getFixedErrataByProduct = (releaseInfo, selectedProduct, selectedVersion) => {
|
|
36
|
+
var _a;
|
|
37
|
+
if (isEmpty(releaseInfo) || !isArray(releaseInfo) || !selectedProduct) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const selectedProductLower = selectedProduct.toLowerCase().trim() || '';
|
|
41
|
+
const selectedVersionLower = ((_a = selectedVersion === null || selectedVersion === void 0 ? void 0 : selectedVersion.toLowerCase()) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
42
|
+
const majorVersion = selectedVersionLower.split('.')[0];
|
|
43
|
+
const filteredArray = releaseInfo.filter((obj) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
const product = (_b = (_a = obj === null || obj === void 0 ? void 0 : obj.product) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === null || _b === void 0 ? void 0 : _b.trim();
|
|
46
|
+
const productVersionMatchConditions = product === selectedProductLower ||
|
|
47
|
+
product === `${selectedProductLower} ${selectedVersionLower}` ||
|
|
48
|
+
(majorVersion && product === `${selectedProductLower} ${majorVersion}`);
|
|
49
|
+
return productVersionMatchConditions && (obj === null || obj === void 0 ? void 0 : obj.state) === 'Fixed';
|
|
50
|
+
});
|
|
51
|
+
return map(filteredArray, (i) => {
|
|
52
|
+
var _a;
|
|
53
|
+
return ({
|
|
54
|
+
package: (i === null || i === void 0 ? void 0 : i.package) || '',
|
|
55
|
+
advisory: isEmpty(i === null || i === void 0 ? void 0 : i.advisory)
|
|
56
|
+
? {}
|
|
57
|
+
: Object.assign(Object.assign({}, i === null || i === void 0 ? void 0 : i.advisory), { url: (_a = (i === null || i === void 0 ? void 0 : i.advisory).url) === null || _a === void 0 ? void 0 : _a.replace(/\\/g, '') }),
|
|
58
|
+
state: (i === null || i === void 0 ? void 0 : i.state) || '',
|
|
59
|
+
product: (i === null || i === void 0 ? void 0 : i.product) || '',
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const sortCveResult = (cveData) => {
|
|
64
|
+
if (isEmpty(cveData)) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const cveSeverity = {
|
|
68
|
+
Critical: 1,
|
|
69
|
+
Important: 2,
|
|
70
|
+
Moderate: 3,
|
|
71
|
+
Low: 4,
|
|
72
|
+
};
|
|
73
|
+
return sortBy(cveData, (item) => { var _a; return cveSeverity[(_a = item === null || item === void 0 ? void 0 : item.data) === null || _a === void 0 ? void 0 : _a.field_cve_threat_severity_text] || Infinity; });
|
|
74
|
+
};
|
|
75
|
+
const fetchCVEData = (cveIds) => __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
if (isEmpty(cveIds))
|
|
77
|
+
return [];
|
|
78
|
+
try {
|
|
79
|
+
const results = yield Promise.allSettled(map(cveIds, (id) => __awaiter(this, void 0, void 0, function* () {
|
|
80
|
+
var _a;
|
|
81
|
+
const cachedData = getFromCache(id);
|
|
82
|
+
if (cachedData) {
|
|
83
|
+
return cachedData;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// sometime backend return html response so we need to handle this scenario so i have added this logic.
|
|
87
|
+
const data = yield search.getCVEDetailsById(id);
|
|
88
|
+
if (((_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.title) === id) {
|
|
89
|
+
setInCache(id, data);
|
|
90
|
+
return data;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
throw new Error('unexpected response');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
})));
|
|
97
|
+
return map(filter(results, (result) => result.status === 'fulfilled'), (result) => result.value);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error('Error fetching CVE data:', error);
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const CVETextValue = `${summary || ''} ${description || ''}`;
|
|
106
|
+
const cveIds = findCVEsInString(CVETextValue);
|
|
107
|
+
fetchCVEData(cveIds)
|
|
108
|
+
.then((results) => {
|
|
109
|
+
const sortedData = sortCveResult(results);
|
|
110
|
+
const processedData = map(sortedData, ({ data }) => {
|
|
111
|
+
var _a, _b, _c, _d;
|
|
112
|
+
return ({
|
|
113
|
+
publicDate: (_a = data === null || data === void 0 ? void 0 : data.field_cve_public_date) === null || _a === void 0 ? void 0 : _a.value,
|
|
114
|
+
title: data === null || data === void 0 ? void 0 : data.title,
|
|
115
|
+
severity: data === null || data === void 0 ? void 0 : data.field_cve_threat_severity_text,
|
|
116
|
+
mitigation: data === null || data === void 0 ? void 0 : data.field_cve_mitigation_text,
|
|
117
|
+
details: (_b = data === null || data === void 0 ? void 0 : data.field_cve_details_text) === null || _b === void 0 ? void 0 : _b.value,
|
|
118
|
+
cveLink: (_c = data === null || data === void 0 ? void 0 : data.path) === null || _c === void 0 ? void 0 : _c.replace(/\\/g, ''),
|
|
119
|
+
errataData: getFixedErrataByProduct(((_d = data === null || data === void 0 ? void 0 : data.field_cve_releases_txt) === null || _d === void 0 ? void 0 : _d.object) || [], product, version),
|
|
120
|
+
});
|
|
121
|
+
}).filter((d) => d.severity !== 'Low');
|
|
122
|
+
setCveRecommendation(processedData);
|
|
123
|
+
setCaseState(caseDispatch, {
|
|
124
|
+
cveWorkflowRecommendation: processedData,
|
|
125
|
+
});
|
|
126
|
+
})
|
|
127
|
+
.catch((error) => {
|
|
128
|
+
console.error('Error processing CVE data:', error);
|
|
129
|
+
});
|
|
130
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
131
|
+
}, [summary, description, product, version, recommendationState === null || recommendationState === void 0 ? void 0 : recommendationState.allDocs]);
|
|
132
|
+
return { cveRecommendation };
|
|
133
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWizard.d.ts","sourceRoot":"","sources":["../../../src/hooks/useWizard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useWizard.d.ts","sourceRoot":"","sources":["../../../src/hooks/useWizard.tsx"],"names":[],"mappings":"AAmCA,UAAU,MAAM;IACZ,yBAAyB,CAAC,EAAE,GAAG,CAAC;IAChC,4BAA4B,EAAE,OAAO,CAAC;IACtC,6BAA6B,EAAE,OAAO,CAAC;IACvC,qCAAqC,EAAE,OAAO,CAAC;IAC/C,aAAa,EAAE,GAAG,CAAC;IACnB,iBAAiB,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,SAAS,CAAC,UAAU,KAAA,EAAE,KAAK,CAAC,EAAE,MAAM;iCAmRb,OAAO;EAwC7C"}
|