@rh-support/troubleshoot 2.4.5-beta.1 → 2.4.5-beta.3

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 (80) hide show
  1. package/lib/esm/components/CaseEditView/CaseDetailsTabs.js +2 -2
  2. package/lib/esm/components/CaseEditView/CaseOverview/CaseType.d.ts.map +1 -1
  3. package/lib/esm/components/CaseEditView/CaseOverview/CaseType.js +4 -18
  4. package/lib/esm/components/CaseEditView/CaseOverview/index.d.ts.map +1 -1
  5. package/lib/esm/components/CaseEditView/CaseOverview/index.js +2 -2
  6. package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutions.d.ts.map +1 -1
  7. package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutions.js +2 -4
  8. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseInternalStatus.d.ts.map +1 -1
  9. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseInternalStatus.js +1 -2
  10. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.d.ts.map +1 -1
  11. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.js +4 -6
  12. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CommentSearch.d.ts.map +1 -1
  13. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CommentSearch.js +2 -3
  14. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts.map +1 -1
  15. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.js +1 -4
  16. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.css +21 -95
  17. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.d.ts.map +1 -1
  18. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.js +137 -269
  19. package/lib/esm/components/CaseInformation/Fts.d.ts.map +1 -1
  20. package/lib/esm/components/CaseInformation/Fts.js +5 -6
  21. package/lib/esm/components/CaseManagement/Cep.d.ts.map +1 -1
  22. package/lib/esm/components/CaseManagement/Cep.js +2 -3
  23. package/lib/esm/components/CaseManagement/RHAssociatesSelector.d.ts.map +1 -1
  24. package/lib/esm/components/CaseManagement/RHAssociatesSelector.js +5 -11
  25. package/lib/esm/components/CaseManagement/SendNotifications/CaseContactSelector.d.ts.map +1 -1
  26. package/lib/esm/components/CaseManagement/SendNotifications/CaseContactSelector.js +5 -11
  27. package/lib/esm/components/Cve/CveItem.d.ts +8 -0
  28. package/lib/esm/components/Cve/CveItem.d.ts.map +1 -0
  29. package/lib/esm/components/Cve/CveItem.js +81 -0
  30. package/lib/esm/components/Cve/CveModal.d.ts +3 -0
  31. package/lib/esm/components/Cve/CveModal.d.ts.map +1 -0
  32. package/lib/esm/components/Cve/CveModal.js +40 -0
  33. package/lib/esm/components/Cve/CvePanel.d.ts +7 -0
  34. package/lib/esm/components/Cve/CvePanel.d.ts.map +1 -0
  35. package/lib/esm/components/Cve/CvePanel.js +23 -0
  36. package/lib/esm/components/Cve/CveSidebar.d.ts +3 -0
  37. package/lib/esm/components/Cve/CveSidebar.d.ts.map +1 -0
  38. package/lib/esm/components/Cve/CveSidebar.js +24 -0
  39. package/lib/esm/components/ProductSelector/ProductSelector.d.ts.map +1 -1
  40. package/lib/esm/components/ProductSelector/ProductSelector.js +4 -0
  41. package/lib/esm/components/Recommendations/AsideResults.d.ts.map +1 -1
  42. package/lib/esm/components/Recommendations/AsideResults.js +2 -4
  43. package/lib/esm/components/Recommendations/EARules/EARule.d.ts.map +1 -1
  44. package/lib/esm/components/Recommendations/EARules/EARule.js +2 -0
  45. package/lib/esm/components/Recommendations/EARules/EARuleInfoInline.d.ts.map +1 -1
  46. package/lib/esm/components/Recommendations/EARules/EARuleInfoInline.js +2 -2
  47. package/lib/esm/components/Recommendations/Recommendations.d.ts.map +1 -1
  48. package/lib/esm/components/Recommendations/Recommendations.js +22 -24
  49. package/lib/esm/components/Recommendations/RecommendationsLoader.d.ts +3 -0
  50. package/lib/esm/components/Recommendations/RecommendationsLoader.d.ts.map +1 -0
  51. package/lib/esm/components/Recommendations/RecommendationsLoader.js +11 -0
  52. package/lib/esm/components/SubmitCase/SubmitCase.js +3 -3
  53. package/lib/esm/components/Suggestions/TopContent.d.ts.map +1 -1
  54. package/lib/esm/components/Suggestions/TopContent.js +4 -1
  55. package/lib/esm/components/shared/fileUpload/fileSelectors/WidgetFileSelector.d.ts +2 -2
  56. package/lib/esm/components/shared/fileUpload/fileSelectors/WidgetFileSelector.d.ts.map +1 -1
  57. package/lib/esm/components/shared/fileUpload/fileSelectors/WidgetFileSelector.js +1 -10
  58. package/lib/esm/components/wizardLayout/WizardAside.d.ts.map +1 -1
  59. package/lib/esm/components/wizardLayout/WizardAside.js +5 -1
  60. package/lib/esm/components/wizardLayout/WizardLayout.d.ts.map +1 -1
  61. package/lib/esm/components/wizardLayout/WizardLayout.js +1 -4
  62. package/lib/esm/components/wizardLayout/WizardMain.d.ts.map +1 -1
  63. package/lib/esm/components/wizardLayout/WizardMain.js +0 -5
  64. package/lib/esm/components/wizardLayout/WizardNavigation.d.ts.map +1 -1
  65. package/lib/esm/components/wizardLayout/WizardNavigation.js +3 -7
  66. package/lib/esm/hooks/useFetchCVEData.d.ts +5 -0
  67. package/lib/esm/hooks/useFetchCVEData.d.ts.map +1 -0
  68. package/lib/esm/hooks/useFetchCVEData.js +101 -0
  69. package/lib/esm/models/caseCreationWorkflows.d.ts +25 -0
  70. package/lib/esm/models/caseCreationWorkflows.d.ts.map +1 -0
  71. package/lib/esm/models/caseCreationWorkflows.js +1 -0
  72. package/lib/esm/reducers/CaseConstNTypes.d.ts +3 -0
  73. package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
  74. package/lib/esm/reducers/CaseConstNTypes.js +2 -0
  75. package/lib/esm/scss/_main.scss +20 -2
  76. package/lib/esm/scss/_pf-overrides.scss +0 -6
  77. package/lib/esm/utils/caseUtils.d.ts +6 -0
  78. package/lib/esm/utils/caseUtils.d.ts.map +1 -1
  79. package/lib/esm/utils/caseUtils.js +15 -0
  80. package/package.json +11 -11
@@ -11,7 +11,6 @@ import { Button, Tooltip, TooltipPosition } from '@patternfly/react-core';
11
11
  import { ToastNotification } from '@rh-support/components';
12
12
  import { GlobalMetadataStateContext } from '@rh-support/react-context';
13
13
  import { AbilityContext, CaseListFields, resourceActions, resources } from '@rh-support/user-permissions';
14
- import { dtmTrackEventCaseStepEncountered } from '@rh-support/utils';
15
14
  import differenceBy from 'lodash/differenceBy';
16
15
  import filter from 'lodash/filter';
17
16
  import find from 'lodash/find';
@@ -32,13 +31,11 @@ function RHAssociatesSelector(props) {
32
31
  const [isRHAssociatesUpdating, setIsRHAssociatesUpdating] = useState(false);
33
32
  const ability = useContext(AbilityContext);
34
33
  const { isExportingPDF } = useContext(PDFContext);
35
- const { caseNumber, contactSsoUsername, product, selectedOwner, selectedNotificationContacts, version } = useCaseSelector((state) => ({
34
+ const { caseNumber, contactSsoUsername, selectedOwner, selectedNotificationContacts } = useCaseSelector((state) => ({
36
35
  caseNumber: state.caseDetails.caseNumber,
37
36
  contactSsoUsername: state.caseDetails.contactSSOName,
38
37
  selectedOwner: state.selectedOwner,
39
38
  selectedNotificationContacts: state.selectedNotificationContacts,
40
- product: state.caseDetails.product,
41
- version: state.caseDetails.version,
42
39
  }), isEqual);
43
40
  const caseDispatch = useCaseDispatch();
44
41
  const onRhAssociateAdded = (addedUsers) => __awaiter(this, void 0, void 0, function* () {
@@ -67,7 +64,7 @@ function RHAssociatesSelector(props) {
67
64
  ToastNotification.addDangerMessage(t(`Red Hat associate failed to get removed`));
68
65
  }
69
66
  });
70
- const onNotifiedUserChange = (selectedContacts_1, ...args_1) => __awaiter(this, [selectedContacts_1, ...args_1], void 0, function* (selectedContacts, throwTrackEventOnAdd = false) {
67
+ const onNotifiedUserChange = (selectedContacts) => __awaiter(this, void 0, void 0, function* () {
71
68
  const toAdd = filter(differenceBy(selectedContacts, selectedNotificationContacts, 'ssoUsername'), (item) => item.ssoUsername !== contactSsoUsername);
72
69
  const toRemove = filter(differenceBy(selectedNotificationContacts, selectedContacts, 'ssoUsername'), (item) => item.isInternal && item.ssoUsername !== contactSsoUsername);
73
70
  let newContacts = [];
@@ -75,9 +72,6 @@ function RHAssociatesSelector(props) {
75
72
  newContacts = [...selectedNotificationContacts, ...toAdd];
76
73
  if (!isEmpty(caseNumber)) {
77
74
  yield onRhAssociateAdded(toAdd);
78
- if (throwTrackEventOnAdd) {
79
- dtmTrackEventCaseStepEncountered('follow', caseNumber, product, version);
80
- }
81
75
  }
82
76
  }
83
77
  else if ((toRemove || []).length > 0) {
@@ -96,9 +90,9 @@ function RHAssociatesSelector(props) {
96
90
  !isCurrentUserSelectedInternalNotifiedUser();
97
91
  const showRemoveWatchButton = () => (loggedInUserRights.data.isInternal() && isCurrentUserSelectedInternalNotifiedUser()) ||
98
92
  contactSsoUsername === loggedInUser.data.ssoUsername;
99
- const addCurrentUser = () => __awaiter(this, void 0, void 0, function* () {
100
- onNotifiedUserChange([Object.assign(Object.assign({}, loggedInUser.data), { accountNumber: loggedInUserRights.data.getAccountNumber() })], true);
101
- });
93
+ const addCurrentUser = () => {
94
+ onNotifiedUserChange([Object.assign(Object.assign({}, loggedInUser.data), { accountNumber: loggedInUserRights.data.getAccountNumber() })]);
95
+ };
102
96
  const removeCurrentUser = () => {
103
97
  if (isCurrentUserSelectedInternalNotifiedUser()) {
104
98
  onNotifiedUserChange(filter(selectedNotificationContacts, (contact) => contact.ssoUsername !== loggedInUser.data.ssoUsername));
@@ -1 +1 @@
1
- {"version":3,"file":"CaseContactSelector.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseManagement/SendNotifications/CaseContactSelector.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAgBvE,MAAM,WAAW,MAAM;CAAG;AAG1B,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBA8bzC;AAED,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"CaseContactSelector.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseManagement/SendNotifications/CaseContactSelector.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAgBvE,MAAM,WAAW,MAAM;CAAG;AAG1B,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBAmbzC;AAED,eAAe,mBAAmB,CAAC"}
@@ -11,7 +11,6 @@ import { Button, Tooltip, TooltipPosition } from '@patternfly/react-core';
11
11
  import { CaseContactsSelectorExternal, getHydraContactLabel, PromisifyModal, ToastNotification, usePrevious, } from '@rh-support/components';
12
12
  import { GlobalMetadataStateContext, useCanEditCase } from '@rh-support/react-context';
13
13
  import { AbilityContext, CaseDetailsFields, resourceActions, resources } from '@rh-support/user-permissions';
14
- import { dtmTrackEventCaseStepEncountered } from '@rh-support/utils';
15
14
  import differenceBy from 'lodash/differenceBy';
16
15
  import filter from 'lodash/filter';
17
16
  import find from 'lodash/find';
@@ -35,7 +34,7 @@ function CaseContactSelector(props) {
35
34
  const canSeeEmailNotifications = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_SEND_NOTIFICATIONS);
36
35
  const [isAssociatesUpdating, setIsAssociatesUpdating] = useState(false);
37
36
  const { t } = useTranslation();
38
- const { accountNumber, caseNumber, contactSsoUsername, selectedNotificationContacts, selectedOwner, customEmailsList, product, selectedCaseGroupUsers, ownersCaseGroups, groupNumber, createdById, version, } = useCaseSelector((state) => ({
37
+ const { accountNumber, caseNumber, contactSsoUsername, selectedNotificationContacts, selectedOwner, customEmailsList, selectedCaseGroupUsers, ownersCaseGroups, groupNumber, createdById, } = useCaseSelector((state) => ({
39
38
  accountNumber: state.caseDetails.accountNumberRef,
40
39
  caseNumber: state.caseDetails.caseNumber,
41
40
  contactSsoUsername: state.caseDetails.contactSSOName,
@@ -46,8 +45,6 @@ function CaseContactSelector(props) {
46
45
  groupNumber: state.caseDetails.groupNumber,
47
46
  ownersCaseGroups: state.ownersCaseGroups,
48
47
  createdById: state.caseDetails.createdById,
49
- product: state.caseDetails.product,
50
- version: state.caseDetails.version,
51
48
  }), isEqual);
52
49
  const caseDispatch = useCaseDispatch();
53
50
  const { addCustomEmail, canAddCustomEmail, hideCustomEmails, deleteCustomEmail, isUpdatingCustomEmails, isEmailValid, showAddEmailToAccountModal, } = useCustomEmails({
@@ -188,7 +185,7 @@ function CaseContactSelector(props) {
188
185
  }
189
186
  return hasGroupAccess;
190
187
  });
191
- const onNotifiedUserChange = (...args_1) => __awaiter(this, [...args_1], void 0, function* (selectedContacts = [], throwTrackEvent = false) {
188
+ const onNotifiedUserChange = (...args_1) => __awaiter(this, [...args_1], void 0, function* (selectedContacts = []) {
192
189
  // check if selection changed
193
190
  const alreadySelected = [
194
191
  ...customEmailsList.data,
@@ -202,9 +199,6 @@ function CaseContactSelector(props) {
202
199
  const selectedCustomEmails = remove(allSelectedContacts, (item) => item.customOption || item.emailAddress).map((item) => item.label || item.emailAddress || item.ssoUsername);
203
200
  yield processCustomEmails(selectedCustomEmails);
204
201
  yield processCaseContacts(allSelectedContacts);
205
- if (throwTrackEvent) {
206
- dtmTrackEventCaseStepEncountered('follow', caseNumber, product, version);
207
- }
208
202
  });
209
203
  /** Reset all non-internal selectedNotificationContacts when selected account number changes */
210
204
  useEffect(() => {
@@ -220,9 +214,9 @@ function CaseContactSelector(props) {
220
214
  !isCurrentUserSelectedExternalNotifiedUser();
221
215
  const showRemoveWatchButton = () => loggedInUserRights.data.isExternal() &&
222
216
  (isCurrentUserSelectedExternalNotifiedUser() || isCurrentUserCaseContact);
223
- const addCurrentUser = () => __awaiter(this, void 0, void 0, function* () {
224
- onNotifiedUserChange([...selectedNotificationContacts, ...customEmailsList.data, loggedInUser.data], true);
225
- });
217
+ const addCurrentUser = () => {
218
+ onNotifiedUserChange([...selectedNotificationContacts, ...customEmailsList.data, loggedInUser.data]);
219
+ };
226
220
  const removeCurrentUser = () => {
227
221
  if (isCurrentUserSelectedExternalNotifiedUser()) {
228
222
  onNotifiedUserChange([
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { ICVEWorkflowRecommendation } from '../../models/caseCreationWorkflows';
3
+ interface IProp {
4
+ cve: ICVEWorkflowRecommendation;
5
+ }
6
+ export declare const CveItem: (props: IProp) => React.JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=CveItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CveItem.d.ts","sourceRoot":"","sources":["../../../../src/components/Cve/CveItem.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAEhF,UAAU,KAAK;IACX,GAAG,EAAE,0BAA0B,CAAC;CACnC;AAID,eAAO,MAAM,OAAO,UAAW,KAAK,sBAqInC,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { Button, Flex, FlexItem, Label, LabelGroup, Text, TextVariants } from '@patternfly/react-core';
2
+ import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon';
3
+ import StarIcon from '@patternfly/react-icons/dist/esm/icons/star-icon';
4
+ import { Table, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table';
5
+ import { format } from 'date-fns';
6
+ import DOMPurify from 'dompurify';
7
+ import isEmpty from 'lodash/isEmpty';
8
+ import map from 'lodash/map';
9
+ import slice from 'lodash/slice';
10
+ import React from 'react';
11
+ import { Trans } from 'react-i18next';
12
+ const sanitize = (html) => ({ __html: DOMPurify.sanitize(html) });
13
+ export const CveItem = (props) => {
14
+ const { cve } = props;
15
+ const renderDate = () => (React.createElement("div", { className: "pf-v5-u-disabled-color-100" },
16
+ React.createElement(Trans, null, "Public on"),
17
+ " - ",
18
+ format(cve === null || cve === void 0 ? void 0 : cve.publicDate, 'MMM dd, yyyy')));
19
+ const renderLabels = () => (React.createElement(LabelGroup, { defaultIsOpen: true, numLabels: 10 },
20
+ React.createElement(Label, { color: "green", isCompact: true, icon: React.createElement(StarIcon, null) },
21
+ React.createElement(Trans, null, "Exact match")),
22
+ React.createElement(Label, { color: cve.severity === 'Critical'
23
+ ? 'red'
24
+ : cve.severity === 'Important'
25
+ ? 'orange'
26
+ : cve.severity === 'Moderate'
27
+ ? 'gold'
28
+ : undefined, isCompact: true }, cve.severity),
29
+ !isEmpty(cve.errataData) && (React.createElement(Label, { color: "blue", isCompact: true },
30
+ React.createElement(Trans, null, "Fixed"))),
31
+ !isEmpty(cve.mitigation) && (React.createElement(Label, { isCompact: true },
32
+ React.createElement(Trans, null, "Mitigation available")))));
33
+ const displayErrataTable = () => {
34
+ if (isEmpty(cve === null || cve === void 0 ? void 0 : cve.errataData)) {
35
+ return null;
36
+ }
37
+ return (React.createElement(Table, { "aria-label": "Errata table", variant: 'compact' },
38
+ React.createElement(Thead, null,
39
+ React.createElement(Tr, null,
40
+ React.createElement(Th, { width: 30 },
41
+ React.createElement(Trans, null, "Errata link")),
42
+ React.createElement(Th, null,
43
+ React.createElement(Trans, null, "Component")),
44
+ React.createElement(Th, { width: 30 },
45
+ React.createElement(Trans, null, "Status")))),
46
+ React.createElement(Tbody, null, map(slice(cve.errataData, 0, 3), (errata, index) => {
47
+ var _a, _b, _c;
48
+ return (React.createElement(Tr, Object.assign({ key: (_a = errata === null || errata === void 0 ? void 0 : errata.advisory) === null || _a === void 0 ? void 0 : _a.name }, (index % 2 === 0 && { isStriped: true })),
49
+ React.createElement(Td, null,
50
+ React.createElement(Text, { component: TextVariants.a, href: (_b = errata === null || errata === void 0 ? void 0 : errata.advisory) === null || _b === void 0 ? void 0 : _b.url, target: "_blank", ouiaSafe: true, "data-tracking-id": "errata-link" }, (_c = errata === null || errata === void 0 ? void 0 : errata.advisory) === null || _c === void 0 ? void 0 :
51
+ _c.name,
52
+ React.createElement(ExternalLinkAltIcon, { className: "pf-v5-u-ml-sm" }))),
53
+ React.createElement(Td, null, errata === null || errata === void 0 ? void 0 : errata.package),
54
+ React.createElement(Td, null,
55
+ React.createElement(Trans, null, errata === null || errata === void 0 ? void 0 : errata.state))));
56
+ }))));
57
+ };
58
+ const displayDescription = () => {
59
+ var _a;
60
+ if (isEmpty(cve === null || cve === void 0 ? void 0 : cve.mitigation) && ((_a = cve === null || cve === void 0 ? void 0 : cve.errataData) === null || _a === void 0 ? void 0 : _a.length) === 0) {
61
+ return (React.createElement("p", { className: "pf-v5-u-mt-md" }, "for this CVE mitigation and fix is not available, for more details, go to CVE page."));
62
+ }
63
+ const MAX_DESCRIPTION_LENGTH = 300;
64
+ const description = !isEmpty(cve === null || cve === void 0 ? void 0 : cve.mitigation) ? cve === null || cve === void 0 ? void 0 : cve.mitigation : cve === null || cve === void 0 ? void 0 : cve.details;
65
+ if (!description)
66
+ return '';
67
+ const trimmedDescription = description.length <= MAX_DESCRIPTION_LENGTH
68
+ ? description
69
+ : description.slice(0, MAX_DESCRIPTION_LENGTH).trim() + '...';
70
+ return React.createElement("p", { className: "pf-v5-u-mt-md", dangerouslySetInnerHTML: sanitize(trimmedDescription) });
71
+ };
72
+ return (React.createElement("p", null,
73
+ React.createElement(Flex, null,
74
+ React.createElement(FlexItem, { spacer: { default: 'spacerXs' } }, renderLabels()),
75
+ React.createElement(FlexItem, null, renderDate())),
76
+ displayErrataTable(),
77
+ displayDescription(),
78
+ (cve === null || cve === void 0 ? void 0 : cve.cveLink) && (React.createElement(Button, { variant: "primary", className: "pf-v5-u-my-md", "data-tracking-id": "go-to-CVE-button", component: "a", href: cve.cveLink, target: "_blank", rel: "noopener noreferrer" },
79
+ React.createElement(Trans, null, "Go to CVE"),
80
+ React.createElement(ExternalLinkAltIcon, { className: "pf-v5-u-ml-sm" })))));
81
+ };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const CveModal: () => React.JSX.Element;
3
+ //# sourceMappingURL=CveModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CveModal.d.ts","sourceRoot":"","sources":["../../../../src/components/Cve/CveModal.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,eAAO,MAAM,QAAQ,yBAuDpB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { Badge, Button, Flex, FlexItem, Modal, ModalVariant } from '@patternfly/react-core';
2
+ import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon';
3
+ import { getAccessHostname } from '@rh-support/utils';
4
+ import isEqual from 'lodash/isEqual';
5
+ import join from 'lodash/join';
6
+ import map from 'lodash/map';
7
+ import size from 'lodash/size';
8
+ import React from 'react';
9
+ import { Trans } from 'react-i18next';
10
+ import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
11
+ import { setCaseState } from '../../reducers/CaseReducer';
12
+ import { CvePanel } from './CvePanel';
13
+ export const CveModal = () => {
14
+ const caseDispatch = useCaseDispatch();
15
+ const { cveWorkflowRecommendation, isCveModalOpened } = useCaseSelector((state) => ({
16
+ cveWorkflowRecommendation: state.cveWorkflowRecommendation,
17
+ isCveModalOpened: state.isCveModalOpened,
18
+ }), isEqual);
19
+ const handleModalToggle = () => {
20
+ setCaseState(caseDispatch, { isCveModalOpened: !isCveModalOpened });
21
+ };
22
+ const handleEscapePress = (event) => {
23
+ // prevent the default escape key behavior
24
+ event.preventDefault();
25
+ };
26
+ const generateCveCheckerUrl = () => {
27
+ const cveTitles = join(map(cveWorkflowRecommendation, 'title'), ',');
28
+ return `https://${getAccessHostname()}/labs/cvechecker/?id=${cveTitles}`;
29
+ };
30
+ return (React.createElement(Modal, { variant: ModalVariant.medium, title: React.createElement(Flex, { alignItems: { default: 'alignItemsCenter' } },
31
+ React.createElement(FlexItem, { spacer: { default: 'spacerSm' } },
32
+ React.createElement(Trans, null, "Handpicked for this CVEs")),
33
+ React.createElement(Badge, { isRead: true }, size(cveWorkflowRecommendation))), isOpen: isCveModalOpened, onClose: handleModalToggle, titleIconVariant: "info", disableFocusTrap: true, onEscapePress: handleEscapePress, actions: [
34
+ React.createElement(Button, { key: "cve-checker-link", "data-tracking-id": "cve-checker-link", target: "_blank", variant: "secondary", isInline: true, component: "a", href: generateCveCheckerUrl() },
35
+ React.createElement(Trans, null, "Red Hat CVE Checker"),
36
+ " ",
37
+ React.createElement(ExternalLinkAltIcon, { className: "pf-v5-u-ml-sm" })),
38
+ ] },
39
+ React.createElement(CvePanel, null)));
40
+ };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface IProps {
3
+ className?: string;
4
+ }
5
+ export declare const CvePanel: (props: IProps) => React.JSX.Element;
6
+ export {};
7
+ //# sourceMappingURL=CvePanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CvePanel.d.ts","sourceRoot":"","sources":["../../../../src/components/Cve/CvePanel.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAMxC,UAAU,MAAM;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,QAAQ,UAAW,MAAM,sBAyCrC,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { Accordion, AccordionContent, AccordionItem, AccordionToggle } from '@patternfly/react-core';
2
+ import isEqual from 'lodash/isEqual';
3
+ import map from 'lodash/map';
4
+ import slice from 'lodash/slice';
5
+ import React, { useState } from 'react';
6
+ import { useCaseSelector } from '../../context/CaseContext';
7
+ import { CveItem } from './CveItem';
8
+ export const CvePanel = (props) => {
9
+ var _a;
10
+ const { cveWorkflowRecommendation } = useCaseSelector((state) => ({
11
+ cveWorkflowRecommendation: state.cveWorkflowRecommendation,
12
+ }), isEqual);
13
+ const [expanded, setExpanded] = useState(((_a = cveWorkflowRecommendation === null || cveWorkflowRecommendation === void 0 ? void 0 : cveWorkflowRecommendation[0]) === null || _a === void 0 ? void 0 : _a.title) || '');
14
+ const handleToggle = (id) => setExpanded(id === expanded ? '' : id);
15
+ const renderAccordionItem = (cve, index) => {
16
+ const isExpanded = expanded === (cve === null || cve === void 0 ? void 0 : cve.title);
17
+ return (React.createElement(AccordionItem, { key: `cve-item-${index}` },
18
+ React.createElement(AccordionToggle, { onClick: () => handleToggle(cve.title), isExpanded: isExpanded, id: `cve-toggle-${index}`, "data-tracking-id": "cve-accordion-toggle" }, cve.title),
19
+ React.createElement(AccordionContent, { id: `cve-content-${index}`, isHidden: !isExpanded },
20
+ React.createElement(CveItem, { cve: cve }))));
21
+ };
22
+ return (React.createElement(Accordion, { isBordered: true, displaySize: 'default', asDefinitionList: false, className: `${props.className ? props.className : ''}` }, map(slice(cveWorkflowRecommendation, 0, 4), renderAccordionItem)));
23
+ };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const CveSidebar: () => React.JSX.Element;
3
+ //# sourceMappingURL=CveSidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CveSidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/Cve/CveSidebar.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,eAAO,MAAM,UAAU,yBAyBtB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { Badge } from '@patternfly/react-core';
2
+ import isEmpty from 'lodash/isEmpty';
3
+ import isEqual from 'lodash/isEqual';
4
+ import size from 'lodash/size';
5
+ import React from 'react';
6
+ import { Trans } from 'react-i18next';
7
+ import { useCaseSelector } from '../../context/CaseContext';
8
+ import { CvePanel } from './CvePanel';
9
+ export const CveSidebar = () => {
10
+ const { cveWorkflowRecommendation } = useCaseSelector((state) => ({
11
+ cveWorkflowRecommendation: state.cveWorkflowRecommendation,
12
+ }), isEqual);
13
+ if (isEmpty(cveWorkflowRecommendation)) {
14
+ return null;
15
+ }
16
+ return (React.createElement(React.Fragment, null,
17
+ React.createElement("div", { className: "card card-white card-support file-diag pf-v5-u-mb-md" },
18
+ React.createElement("h3", { className: "card-heading popular-solutions green-card-heading" },
19
+ React.createElement("span", { className: "pf-v5-u-mr-sm" },
20
+ React.createElement(Trans, null, "Handpicked for this CVEs")),
21
+ React.createElement(Badge, { isRead: true }, size(cveWorkflowRecommendation))),
22
+ React.createElement("div", { className: "card-body" },
23
+ React.createElement(CvePanel, null)))));
24
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"ProductSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ProductSelector/ProductSelector.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAMlE,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,gCAAgC,EAAE,OAAO,CAAC;IAC1C,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,MAAM,qBAsFpD"}
1
+ {"version":3,"file":"ProductSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ProductSelector/ProductSelector.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAKvD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAOlE,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,gCAAgC,EAAE,OAAO,CAAC;IAC1C,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,MAAM,qBAwFpD"}
@@ -7,6 +7,8 @@ import React, { useContext, useRef } from 'react';
7
7
  import { Trans, useTranslation } from 'react-i18next';
8
8
  import { useCaseSelector } from '../../context/CaseContext';
9
9
  import { RouteContext } from '../../context/RouteContext';
10
+ import { useFetchCVEData } from '../../hooks/useFetchCVEData';
11
+ import { CveModal } from '../Cve/CveModal';
10
12
  import { EARuleWidget } from '../Recommendations/EARules/EARuleWidget';
11
13
  import Recommendations from '../Recommendations/Recommendations';
12
14
  import { AllProductsSelector } from './AllProductsSelector';
@@ -20,6 +22,7 @@ import { ProductSelectorLoader } from './ProductSelectorLoader';
20
22
  * @param props
21
23
  */
22
24
  export default function ProductSelector(props) {
25
+ const { cveRecommendation } = useFetchCVEData();
23
26
  const { t } = useTranslation();
24
27
  const { globalMetadataState: { allProducts }, } = useContext(GlobalMetadataStateContext);
25
28
  const { product, version } = useCaseSelector((state) => ({
@@ -38,6 +41,7 @@ export default function ProductSelector(props) {
38
41
  React.createElement(AlertMessage, { variant: AlertType.DANGER, className: "pf-v5-u-mt-lg", title: t('There was an error loading products.'), show: allProducts.isError }),
39
42
  !allProducts.isFetching && !allProducts.isError && (React.createElement(React.Fragment, null,
40
43
  React.createElement("form", null,
44
+ (cveRecommendation === null || cveRecommendation === void 0 ? void 0 : cveRecommendation.length) !== 0 && React.createElement(CveModal, null),
41
45
  React.createElement(AllProductsSelector, { routeProps: props.routeProps, checkEntitledProduct: isCaseCreate ? true : false, ref: productSelectorRef, isOnSummaryPage: true }),
42
46
  product === 'Subscription Watch' && (React.createElement(Alert, { isInline: true, variant: AlertVariant.warning, title: React.createElement(Trans, null,
43
47
  ' ',
@@ -1 +1 @@
1
- {"version":3,"file":"AsideResults.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/AsideResults.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AASvD,OAAO,EAAE,eAAe,EAAsC,MAAM,iCAAiC,CAAC;AAUtG,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,qBA0MzC"}
1
+ {"version":3,"file":"AsideResults.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/AsideResults.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AASvD,OAAO,EAAE,eAAe,EAAsC,MAAM,iCAAiC,CAAC;AAUtG,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,qBAyLzC"}
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { pcm, search } from '@cee-eng/hydrajs';
11
11
  import { useDebounce } from '@rh-support/components';
12
- import { computeRecommendationAbstract, computeRecommendationTitle, convertObjToEncodedQueryParams, dtmTrackEventRecommendationListingItemClicked, getSolrParams, getTrimmedCharacters, PreviousCaseTypes, replaceHighlightingData, } from '@rh-support/utils';
12
+ import { computeRecommendationAbstract, computeRecommendationTitle, convertObjToEncodedQueryParams, getSolrParams, getTrimmedCharacters, PreviousCaseTypes, replaceHighlightingData, } from '@rh-support/utils';
13
13
  import isEmpty from 'lodash/isEmpty';
14
14
  import isEqual from 'lodash/isEqual';
15
15
  import React, { useContext, useEffect, useRef } from 'react';
@@ -117,9 +117,7 @@ export function AsideResults(props) {
117
117
  const onResourceClick = (doc, index) => (event) => {
118
118
  if (isSelectedAccounntSecureSupport)
119
119
  return;
120
- const rank = index + 1 + PAGE_SIZE * ((recommendationState.currentPage || 1) - 1);
121
120
  createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS_ASIDE, [getSessResFromRec(doc, SessionResourceVisibility.VISITED, index + 1)], payload);
122
- dtmTrackEventRecommendationListingItemClicked(window.location.href, activeSection, 'middle', doc.id, rank, doc.allTitle, doc.view_uri, 'Recommendation Aside', 'Live troubleshooting powered by OpenShift AI');
123
121
  };
124
122
  useEffect(() => {
125
123
  if (isSelectedAccounntSecureSupport)
@@ -131,7 +129,7 @@ export function AsideResults(props) {
131
129
  if (!canShowSideRecommendations())
132
130
  return React.createElement(React.Fragment, null);
133
131
  return (React.createElement("div", { className: `card card-white card-support top-recommendations ${props.className ? props.className : ''}` },
134
- React.createElement("h3", { className: "card-heading popular-solutions green-card-heading" }, isIdea ? (React.createElement(Trans, null, "Search recommendations")) : (React.createElement(Trans, null, "Live troubleshooting powered by OpenShift AI"))),
132
+ React.createElement("h3", { className: "card-heading popular-solutions green-card-heading" }, isIdea ? React.createElement(Trans, null, "Search recommendations") : React.createElement(Trans, null, "Articles recommended by OpenShift AI")),
135
133
  React.createElement("div", { className: "card-body" },
136
134
  React.createElement("ul", { className: "list-flat" }, recommendationState.sideRecommendation.map((doc, index) => {
137
135
  var _a, _b;
@@ -1 +1 @@
1
- {"version":3,"file":"EARule.d.ts","sourceRoot":"","sources":["../../../../../src/components/Recommendations/EARules/EARule.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,UAAU,cAAc;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;CAClH;AAGD,eAAO,MAAM,aAAa,+BAGxB,CAAC;AAEH,wBAAgB,gBAAgB,mBAM/B;AACD,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;;;;CAAA,qBAoClD;AAED,iBAAS,WAAW,sBAGnB;AAED,iBAAS,iBAAiB,sBA0BzB;AAED,iBAAS,aAAa,CAAC,EAAE,SAA6B,EAAE,SAAc,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,qBA2BnH;AAED,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"EARule.d.ts","sourceRoot":"","sources":["../../../../../src/components/Recommendations/EARules/EARule.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,UAAU,cAAc;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;CAClH;AAGD,eAAO,MAAM,aAAa,+BAGxB,CAAC;AAEH,wBAAgB,gBAAgB,mBAM/B;AACD,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;;;;CAAA,qBAqClD;AAED,iBAAS,WAAW,sBAGnB;AAED,iBAAS,iBAAiB,sBA0BzB;AAED,iBAAS,aAAa,CAAC,EAAE,SAA6B,EAAE,SAAc,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,qBA2BnH;AAED,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,CAAC"}
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  import { pcm } from '@cee-eng/hydrajs';
3
+ import { dtmTrackEventCaseStartStopped } from '@rh-support/utils';
3
4
  import DOMPurify from 'dompurify';
4
5
  import isEqual from 'lodash/isEqual';
5
6
  import React, { useContext } from 'react';
@@ -30,6 +31,7 @@ export function EARule({ children, rule, ruleRank }) {
30
31
  const sessionRestoreDispatch = useContext(SessionRestoreDispatchContext);
31
32
  const onCtaClick = (link, title) => () => {
32
33
  createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.EDMOUND_ABOTT, [getSessResFromEA(link, SessionResourceVisibility.VISITED, ruleRank, rule.rule_id)], JSON.stringify({ product, version, summary }));
34
+ dtmTrackEventCaseStartStopped(`insight rule button click: ${title}`, undefined, `${product}|${version}`);
33
35
  };
34
36
  return (React.createElement(EARuleContext.Provider, { value: {
35
37
  rule,
@@ -1 +1 @@
1
- {"version":3,"file":"EARuleInfoInline.d.ts","sourceRoot":"","sources":["../../../../../src/components/Recommendations/EARules/EARuleInfoInline.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAM/D,OAAO,EAAE,aAAa,EAAkD,MAAM,gCAAgC,CAAC;AAO/G,UAAU,MAAM;IACZ,OAAO,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,OAAY,EAAE,EAAE,MAAM,qBAwJxD"}
1
+ {"version":3,"file":"EARuleInfoInline.d.ts","sourceRoot":"","sources":["../../../../../src/components/Recommendations/EARules/EARuleInfoInline.tsx"],"names":[],"mappings":"AAeA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAM/D,OAAO,EAAE,aAAa,EAAkD,MAAM,gCAAgC,CAAC;AAO/G,UAAU,MAAM;IACZ,OAAO,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,EAAE,OAAY,EAAE,EAAE,MAAM,qBAiKxD"}
@@ -14,7 +14,7 @@ import CloseIcon from '@patternfly/react-icons/dist/js/icons/close-icon';
14
14
  import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
15
15
  import { PaginationCompact, useFetch } from '@rh-support/components';
16
16
  import { GlobalMetadataStateContext } from '@rh-support/react-context';
17
- import { getResTypeFromUrl, getStyleVariantColor, StyleVariants } from '@rh-support/utils';
17
+ import { dtmTrackEventCaseStartStopped, getResTypeFromUrl, getStyleVariantColor, StyleVariants, } from '@rh-support/utils';
18
18
  import isEqual from 'lodash/isEqual';
19
19
  import some from 'lodash/some';
20
20
  import React, { useContext, useEffect, useState } from 'react';
@@ -102,7 +102,7 @@ export function EARuleInfoInline({ eaRules = [] }) {
102
102
  React.createElement(EARuleTitle, null))),
103
103
  React.createElement("div", { className: "pf-v5-c-alert__action" },
104
104
  React.createElement(Button, { style: { fontSize: 15 }, variant: ButtonVariant.link, "data-tracking-id": "se-recommended-asa-ignore", type: "button", onClick: onIgnoreBtnClick }, validEARulesLength > 1 ? React.createElement(Trans, null, "Skip") : React.createElement(CloseIcon, null))),
105
- React.createElement("div", { className: "pf-v5-c-alert__description" },
105
+ React.createElement("div", { className: "pf-v5-c-alert__description", onClick: () => dtmTrackEventCaseStartStopped('insight rule description click', undefined, `${product}|${version}`) },
106
106
  React.createElement(EARuleDescription, null)),
107
107
  React.createElement("div", { className: "pf-v5-c-alert__action-group pf-v5-u-display-flex" },
108
108
  React.createElement(EARuleArticle, { className: "pf-v5-u-align-self-center pf-v5-u-mr-sm", linkTitle: "View details" }),
@@ -1 +1 @@
1
- {"version":3,"file":"Recommendations.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/Recommendations.tsx"],"names":[],"mappings":"AAmBA,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,qBA+SpD"}
1
+ {"version":3,"file":"Recommendations.d.ts","sourceRoot":"","sources":["../../../../src/components/Recommendations/Recommendations.tsx"],"names":[],"mappings":"AAmBA,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,qBAoSpD"}
@@ -1,8 +1,9 @@
1
1
  import { pcm } from '@cee-eng/hydrajs';
2
- import { Label, Pagination, PaginationVariant } from '@patternfly/react-core';
3
- import { LoadingDots, useDebounce, usePrevious } from '@rh-support/components';
2
+ import { Label, Pagination, PaginationVariant, Spinner } from '@patternfly/react-core';
3
+ import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
4
+ import { useDebounce, usePrevious } from '@rh-support/components';
4
5
  import { useGlobalStateContext } from '@rh-support/react-context';
5
- import { computeRecommendationAbstract, computeRecommendationTitle, dtmTrackEventRecommendationListingDisplayed, dtmTrackEventRecommendationListingItemClicked, formatDate, } from '@rh-support/utils';
6
+ import { computeRecommendationAbstract, computeRecommendationTitle, dtmTrackEventCaseStartStopped, formatDate, } from '@rh-support/utils';
6
7
  import differenceBy from 'lodash/differenceBy';
7
8
  import isEmpty from 'lodash/isEmpty';
8
9
  import isEqual from 'lodash/isEqual';
@@ -20,6 +21,7 @@ import { fetchRecommendations, fetchWatsonXRecommendations, RecommendationsConst
20
21
  import { AppRouteSections } from '../../reducers/RouteConstNTypes';
21
22
  import { createOrUpdateSessionResources, getSessResFromRec, getSessResFromRecs, } from '../../reducers/SessionRestoreReducer';
22
23
  import RouteUtils from '../../utils/routeUtils';
24
+ import { RecommendationsLoader } from './RecommendationsLoader';
23
25
  import { WatsonxAiIcon } from './WatsonxAiIcon';
24
26
  const { SessionResourceSource, SessionResourceVisibility } = pcm.preCase.session;
25
27
  export default function Recommendations(props) {
@@ -121,18 +123,6 @@ export default function Recommendations(props) {
121
123
  setCaseRecommendations(caseDispatch, recommendationState.visibleDocs, caseResourceLinks);
122
124
  }
123
125
  createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS, getSessResFromRecs(recommendationState.visibleDocs, SessionResourceVisibility.PRESENTED, pageSize || DEFAULTPAGESIZE, recommendationState.currentPage || 1), JSON.stringify(payload));
124
- const listing = recommendationState.visibleDocs.map((doc, i) => ({
125
- content: {
126
- contentID: doc.id,
127
- contentPosition: i + 1,
128
- contentTitle: doc.publishedTitle,
129
- contentUrl: doc.view_uri,
130
- displayFeature: 'Troubleshooting',
131
- displayFeatureTitle: '',
132
- },
133
- isDisplayed: true,
134
- }));
135
- dtmTrackEventRecommendationListingDisplayed('middle', activeSection, listing, recommendationState.numFound);
136
126
  // eslint-disable-next-line react-hooks/exhaustive-deps
137
127
  }, [caseDispatch, recommendationState.visibleDocs, activeSessionId]);
138
128
  useEffect(() => {
@@ -157,17 +147,25 @@ export default function Recommendations(props) {
157
147
  setCurrentPage(recommendationDispatch, 1);
158
148
  };
159
149
  const onResourceClick = (doc, index) => (event) => {
160
- const rank = index + 1 + (pageSize || DEFAULTPAGESIZE) * ((recommendationState.currentPage || 1) - 1);
161
- createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS, [getSessResFromRec(doc, SessionResourceVisibility.VISITED, rank)], JSON.stringify(payload));
162
- dtmTrackEventRecommendationListingItemClicked(window.location.href, activeSection, 'middle', doc.id, rank, doc.allTitle, doc.view_uri, 'Main Recommendation', 'Live search results powered by OpenShift AI');
150
+ createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.RECOMMENDATIONS, [
151
+ getSessResFromRec(doc, SessionResourceVisibility.VISITED, index + 1 + (pageSize || DEFAULTPAGESIZE) * ((recommendationState.currentPage || 1) - 1)),
152
+ ], JSON.stringify(payload));
153
+ dtmTrackEventCaseStartStopped('recommendation click', caseNumber, `${product}|${version}`);
163
154
  };
164
155
  return (React.createElement(React.Fragment, null,
165
- React.createElement(LoadingDots, { className: "recommendation-loading-dots", show: recommendationState.isLoadingRecommendations && !isEmpty(summary) && !isEmpty(issue) }),
166
156
  React.createElement("div", { className: "recommendation-list pf-v5-u-pt-md", ref: props.resultsRowRef },
167
- recommendationState.visibleDocs.length !== 0 && (React.createElement(Label, { color: "purple", className: "pf-v5-u-mb-md" },
168
- React.createElement(WatsonxAiIcon, { fillColor: "#6753ac", className: "pf-v5-u-mr-xs" }),
169
- React.createElement(Trans, null, "Live search results powered by OpenShift AI"))),
170
- React.createElement("ul", { className: "list-flat" }, map(recommendationState.visibleDocs, (doc, i) => {
157
+ (recommendationState.visibleDocs.length !== 0 || recommendationState.isLoadingRecommendations) && (React.createElement(Label, { id: "DeepPurpleColorAILabel", className: "pf-v5-u-mb-md" },
158
+ recommendationState.isLoadingRecommendations ? (React.createElement(React.Fragment, null,
159
+ React.createElement(Spinner, { size: "sm", className: "pf-v5-u-mr-xs" }),
160
+ ' ',
161
+ React.createElement(Trans, null, "Recommending articles using OpenShift AI"))) : (React.createElement(React.Fragment, null,
162
+ React.createElement(WatsonxAiIcon, { fillColor: "#FFFFFF", className: "pf-v5-u-mr-xs" }),
163
+ ' ',
164
+ React.createElement(Trans, null, "Articles recommended by OpenShift AI"))),
165
+ ' ',
166
+ React.createElement(InfoCircleIcon, { color: "white" }))),
167
+ recommendationState.isLoadingRecommendations ? ( // as much as it pains me to add these <br /> the pf docs has it this way
168
+ React.createElement(RecommendationsLoader, null)) : (React.createElement("ul", { className: "list-flat" }, map(recommendationState.visibleDocs, (doc, i) => {
171
169
  var _a, _b;
172
170
  return (React.createElement("li", { className: "result", key: doc.id },
173
171
  React.createElement("header", { className: "result-header" },
@@ -180,7 +178,7 @@ export default function Recommendations(props) {
180
178
  React.createElement("span", { className: "list-separator" }, "\u2013"),
181
179
  React.createElement("time", { className: "moment_date meta", title: doc.lastModifiedDate.toString() }, formatDate(doc.lastModifiedDate)))),
182
180
  React.createElement("p", { className: "result-body", dangerouslySetInnerHTML: computeRecommendationAbstract(doc, 300) })));
183
- })),
181
+ }))),
184
182
  recommendationState.numFound !== 0 && recommendationState.numFound > DEFAULTPAGESIZE && (React.createElement("div", { className: "pagination-footer" },
185
183
  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 })))),
186
184
  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
+ };
@@ -168,11 +168,11 @@ export default function SubmitCase(props) {
168
168
  React.createElement("div", { className: "submit-case-header-container" },
169
169
  React.createElement("p", { className: "kicker kicker-sm pf-v5-u-mb-sm" }, !isEmpty(RouteUtils.seBasePath) &&
170
170
  !isUploadingAttachment(attachmentState.caseFiles.selectedLocalFiles) ? (React.createElement(React.Fragment, null,
171
- React.createElement("div", { className: "submit-page-title pf-v5-u-mb-lg" },
171
+ React.createElement("div", { role: "alert", className: "submit-page-title pf-v5-u-mb-lg" },
172
172
  React.createElement(Icon, { className: "submit-case-check-icon pf-v5-u-mt-sm", size: "lg" },
173
173
  React.createElement(CheckCircleIcon, null)),
174
174
  ' ',
175
- React.createElement(Text, { role: "alert", className: "pf-v5-u-mb-0", component: TextVariants.h1 },
175
+ React.createElement(Text, { className: "pf-v5-u-mb-0", component: TextVariants.h1 },
176
176
  React.createElement(Trans, null, "We've added your case to our queue"))),
177
177
  React.createElement("div", { className: "pf-v5-u-mt-sm" },
178
178
  React.createElement(Trans, null, "Case number:"),
@@ -184,7 +184,7 @@ export default function SubmitCase(props) {
184
184
  React.createElement(Icon, { size: "lg", className: "submit-case-check-icon" },
185
185
  React.createElement(CheckCircleIcon, null)),
186
186
  ' ',
187
- React.createElement(Text, { role: "alert", component: TextVariants.h1 },
187
+ React.createElement(Text, { component: TextVariants.h1 },
188
188
  React.createElement(Trans, null, "We\u2019ve added your case to our queue"))),
189
189
  React.createElement(React.Fragment, null,
190
190
  React.createElement(Trans, null, "Case number: "),
@@ -1 +1 @@
1
- {"version":3,"file":"TopContent.d.ts","sourceRoot":"","sources":["../../../../src/components/Suggestions/TopContent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,2DAA2D,CAAC;AAIxF,OAAO,KAAmB,MAAM,OAAO,CAAC;AASxC,UAAU,MAAM;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,KAAK,EAAE,MAAM,qBA8I/C"}
1
+ {"version":3,"file":"TopContent.d.ts","sourceRoot":"","sources":["../../../../src/components/Suggestions/TopContent.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,2DAA2D,CAAC;AAKxF,OAAO,KAAmB,MAAM,OAAO,CAAC;AASxC,UAAU,MAAM;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,KAAK,EAAE,MAAM,qBAiJ/C"}