@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.
Files changed (75) hide show
  1. package/lib/esm/components/AccountInfo/OwnerSelector.d.ts.map +1 -1
  2. package/lib/esm/components/AccountInfo/OwnerSelector.js +1 -1
  3. package/lib/esm/components/CaseInformation/Description.d.ts.map +1 -1
  4. package/lib/esm/components/CaseInformation/Description.js +20 -16
  5. package/lib/esm/components/Cve/CveItem.d.ts +8 -0
  6. package/lib/esm/components/Cve/CveItem.d.ts.map +1 -0
  7. package/lib/esm/components/Cve/CveItem.js +86 -0
  8. package/lib/esm/components/Cve/CveModal.d.ts +3 -0
  9. package/lib/esm/components/Cve/CveModal.d.ts.map +1 -0
  10. package/lib/esm/components/Cve/CveModal.js +42 -0
  11. package/lib/esm/components/Cve/CvePanel.d.ts +7 -0
  12. package/lib/esm/components/Cve/CvePanel.d.ts.map +1 -0
  13. package/lib/esm/components/Cve/CvePanel.js +23 -0
  14. package/lib/esm/components/Cve/CveSidebar.d.ts +3 -0
  15. package/lib/esm/components/Cve/CveSidebar.d.ts.map +1 -0
  16. package/lib/esm/components/Cve/CveSidebar.js +24 -0
  17. package/lib/esm/components/OpenCase/OpenCase.d.ts +3 -0
  18. package/lib/esm/components/OpenCase/OpenCase.d.ts.map +1 -1
  19. package/lib/esm/components/OpenCase/OpenCase.js +8 -0
  20. package/lib/esm/components/ProductSelector/AllProductsSelector.d.ts +3 -0
  21. package/lib/esm/components/ProductSelector/AllProductsSelector.d.ts.map +1 -1
  22. package/lib/esm/components/ProductSelector/AllProductsSelector.js +29 -21
  23. package/lib/esm/components/ProductSelector/NewProductDropdownSelector.d.ts +1 -0
  24. package/lib/esm/components/ProductSelector/NewProductDropdownSelector.d.ts.map +1 -1
  25. package/lib/esm/components/ProductSelector/NewProductDropdownSelector.js +2 -2
  26. package/lib/esm/components/ProductSelector/NewProductVersionSelector.js +1 -1
  27. package/lib/esm/components/ProductSelector/ProductSelector.d.ts +4 -2
  28. package/lib/esm/components/ProductSelector/ProductSelector.d.ts.map +1 -1
  29. package/lib/esm/components/ProductSelector/ProductSelector.js +12 -7
  30. package/lib/esm/components/ProductSelector/ProductVersionDropdownSelector.d.ts.map +1 -1
  31. package/lib/esm/components/ProductSelector/ProductVersionDropdownSelector.js +1 -1
  32. package/lib/esm/components/Recommendations/AsideResults.d.ts.map +1 -1
  33. package/lib/esm/components/Recommendations/AsideResults.js +2 -2
  34. package/lib/esm/components/Recommendations/EARules/EARuleWidget.d.ts.map +1 -1
  35. package/lib/esm/components/Recommendations/EARules/EARuleWidget.js +5 -6
  36. package/lib/esm/components/Recommendations/Recommendations.d.ts.map +1 -1
  37. package/lib/esm/components/Recommendations/Recommendations.js +54 -15
  38. package/lib/esm/components/Recommendations/RecommendationsLoader.d.ts +3 -0
  39. package/lib/esm/components/Recommendations/RecommendationsLoader.d.ts.map +1 -0
  40. package/lib/esm/components/Recommendations/RecommendationsLoader.js +11 -0
  41. package/lib/esm/components/Review/Review.d.ts.map +1 -1
  42. package/lib/esm/components/Review/Review.js +1 -1
  43. package/lib/esm/components/SessionRestore/SessionRestore.js +1 -1
  44. package/lib/esm/components/shared/useIsSectionValid.d.ts.map +1 -1
  45. package/lib/esm/components/shared/useIsSectionValid.js +14 -7
  46. package/lib/esm/components/wizardLayout/WizardAside.d.ts.map +1 -1
  47. package/lib/esm/components/wizardLayout/WizardAside.js +11 -9
  48. package/lib/esm/components/wizardLayout/WizardNavigation.d.ts.map +1 -1
  49. package/lib/esm/components/wizardLayout/WizardNavigation.js +28 -22
  50. package/lib/esm/css/results.css +6 -0
  51. package/lib/esm/hooks/useFetchCVEData.d.ts +5 -0
  52. package/lib/esm/hooks/useFetchCVEData.d.ts.map +1 -0
  53. package/lib/esm/hooks/useFetchCVEData.js +133 -0
  54. package/lib/esm/hooks/useWizard.d.ts.map +1 -1
  55. package/lib/esm/hooks/useWizard.js +11 -3
  56. package/lib/esm/models/caseCreationWorkflows.d.ts +25 -0
  57. package/lib/esm/models/caseCreationWorkflows.d.ts.map +1 -0
  58. package/lib/esm/models/caseCreationWorkflows.js +1 -0
  59. package/lib/esm/reducers/CaseConstNTypes.d.ts +4 -0
  60. package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
  61. package/lib/esm/reducers/CaseConstNTypes.js +3 -0
  62. package/lib/esm/reducers/CaseReducer.d.ts +1 -1
  63. package/lib/esm/reducers/CaseReducer.d.ts.map +1 -1
  64. package/lib/esm/reducers/CaseReducer.js +13 -9
  65. package/lib/esm/reducers/RouteConstNTypes.d.ts +0 -1
  66. package/lib/esm/reducers/RouteConstNTypes.d.ts.map +1 -1
  67. package/lib/esm/reducers/RouteConstNTypes.js +0 -1
  68. package/lib/esm/reducers/SessionRestoreReducer.d.ts +1 -1
  69. package/lib/esm/reducers/SessionRestoreReducer.d.ts.map +1 -1
  70. package/lib/esm/reducers/SessionRestoreReducer.js +15 -122
  71. package/lib/esm/scss/_main.scss +19 -0
  72. package/lib/esm/utils/caseUtils.d.ts +6 -0
  73. package/lib/esm/utils/caseUtils.d.ts.map +1 -1
  74. package/lib/esm/utils/caseUtils.js +15 -0
  75. 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,sBAqD3B"}
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, issue } = useCaseSelector((state) => ({
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
- !isEmpty(issue) &&
32
- createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.EDMOUND_ABOTT, [
33
- getSessResFromRules(visibleValidEARules.cta, SessionResourceVisibility.PRESENTED, 1, visibleValidEARules.rule_id),
34
- ], JSON.stringify({ product, version, summary, description: issue }));
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":"AAkBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AAelE,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAWpF,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,qBA0RpD"}
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 pf-v5-u-pt-md", ref: props.resultsRowRef },
156
- recommendationState.visibleDocs.length !== 0 && (React.createElement(Label, { color: "purple", className: "pf-v5-u-mb-md" },
157
- React.createElement(WatsonxAiIcon, { fillColor: "#6753ac", className: "pf-v5-u-mr-xs" }),
158
- React.createElement(Trans, null, "Live search results powered by OpenShift AI"))),
159
- React.createElement("ul", { className: "list-flat" }, map(recommendationState.visibleDocs, (doc, i) => {
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,3 @@
1
+ import React from 'react';
2
+ export declare const RecommendationsLoader: () => React.JSX.Element;
3
+ //# sourceMappingURL=RecommendationsLoader.d.ts.map
@@ -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,qBA6E3C"}
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(React.Fragment, null,
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;;;;;EAuM9D"}
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
- return (!isEmpty(caseType) &&
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
- return (!isEmpty(product) &&
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,EAKlB,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,qBAsDjC;kBAtDQ,WAAW;;;AAwDpB,eAAe,WAAW,CAAC"}
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, showRecommendationTipsSections, showSideBarClusterIdRuleWidgetSections, showSideBarEARuleWidgetSections, showSideBarFileRecommendationSections, } from '../../reducers/RouteConstNTypes';
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 canshowEARuleWidget = showSideBarEARuleWidgetSections.includes(activeSection);
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
- canshowEARuleWidget && activeSection !== AppRouteSections.GET_SUPPORT && React.createElement(EARuleWidget, null),
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,qBA4OtC;kBA5OQ,gBAAgB;;;AA8OzB,eAAe,gBAAgB,CAAC"}
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 (entry.isIntersecting) {
74
- setHasUserScrolled(true);
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
- if (props.userClickedNextonRecommendationsFn) {
77
- props.userClickedNextonRecommendationsFn(true);
78
- }
91
+ props.userClickedNextonRecommendationsFn && props.userClickedNextonRecommendationsFn(true);
79
92
  }
80
93
  }, {
81
94
  root: null,
82
- threshold: 0.6, // trigger when 60% of element in view
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, setHasUserScrolled, props]);
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 (!props.userClickedNextonRecommendationsValue) {
100
- if (!hasUserScrolled) {
101
- scrollIntoView(props.resultsRowRef, {
102
- navBarRef,
103
- timeout: 0,
104
- onlyIfNotInViewport: true,
105
- offset: 120,
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))
@@ -188,3 +188,9 @@
188
188
  .top-recommendations .card-body .file-results-aside .result .btn-incident-info {
189
189
  font-size: 12px;
190
190
  }
191
+
192
+ .match-label {
193
+ height: 1.25rem;
194
+ margin: 0 0.5rem 0.25rem 0 !important;
195
+ font-weight: 200 !important;
196
+ }
@@ -0,0 +1,5 @@
1
+ import { ICVEWorkflowRecommendation } from '../models/caseCreationWorkflows';
2
+ export declare function useFetchCVEData(): {
3
+ cveRecommendation: ICVEWorkflowRecommendation[];
4
+ };
5
+ //# sourceMappingURL=useFetchCVEData.d.ts.map
@@ -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":"AA+BA,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;iCAgQb,OAAO;EAwC7C"}
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"}