@rh-support/troubleshoot 2.6.103 → 2.6.118

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 (50) hide show
  1. package/lib/esm/components/AccountInfo/AccountSelector.js +1 -1
  2. package/lib/esm/components/CaseEditView/Case.d.ts.map +1 -1
  3. package/lib/esm/components/CaseEditView/Case.js +1 -1
  4. package/lib/esm/components/CaseEditView/Tabs/CaseSummary/CaseSummary.js +3 -3
  5. package/lib/esm/components/CaseEditView/Tabs/CaseSummary/CaseSummaryErrorMessage.js +1 -1
  6. package/lib/esm/components/CaseInformation/Description.d.ts.map +1 -1
  7. package/lib/esm/components/CaseInformation/Description.js +3 -1
  8. package/lib/esm/components/OpenCase/OpenCase.d.ts.map +1 -1
  9. package/lib/esm/components/OpenCase/OpenCase.js +2 -8
  10. package/lib/esm/components/ProductSelector/AllProductsSelector.d.ts.map +1 -1
  11. package/lib/esm/components/ProductSelector/AllProductsSelector.js +6 -18
  12. package/lib/esm/components/ProductSelector/ProductSelector.d.ts.map +1 -1
  13. package/lib/esm/components/ProductSelector/ProductSelector.js +5 -12
  14. package/lib/esm/components/Recommendations/Recommendations.d.ts.map +1 -1
  15. package/lib/esm/components/Recommendations/Recommendations.js +38 -38
  16. package/lib/esm/components/RemoteRider/RemoteRiderAcceptanceModal.d.ts.map +1 -1
  17. package/lib/esm/components/Review/Review.d.ts.map +1 -1
  18. package/lib/esm/components/Review/Review.js +1 -5
  19. package/lib/esm/components/Suggestions/TopContentSidebar.d.ts +3 -0
  20. package/lib/esm/components/Suggestions/TopContentSidebar.d.ts.map +1 -0
  21. package/lib/esm/components/Suggestions/TopContentSidebar.js +26 -0
  22. package/lib/esm/components/TroubleshootSection/AskRedHat.js +1 -1
  23. package/lib/esm/components/TroubleshootSection/TroubleshootSection.d.ts +9 -0
  24. package/lib/esm/components/TroubleshootSection/TroubleshootSection.d.ts.map +1 -1
  25. package/lib/esm/components/TroubleshootSection/TroubleshootSection.js +150 -44
  26. package/lib/esm/components/shared/useIsSectionValid.d.ts.map +1 -1
  27. package/lib/esm/components/shared/useIsSectionValid.js +26 -65
  28. package/lib/esm/components/wizardLayout/WizardAside.d.ts.map +1 -1
  29. package/lib/esm/components/wizardLayout/WizardAside.js +18 -9
  30. package/lib/esm/components/wizardLayout/WizardMain.d.ts.map +1 -1
  31. package/lib/esm/components/wizardLayout/WizardMain.js +110 -64
  32. package/lib/esm/components/wizardLayout/WizardNavigation.d.ts.map +1 -1
  33. package/lib/esm/components/wizardLayout/WizardNavigation.js +59 -53
  34. package/lib/esm/css/AskRedHat.css +9 -2
  35. package/lib/esm/hooks/useAB.d.ts +22 -0
  36. package/lib/esm/hooks/useAB.d.ts.map +1 -0
  37. package/lib/esm/hooks/useAB.js +37 -0
  38. package/lib/esm/hooks/useWizard.d.ts +4 -0
  39. package/lib/esm/hooks/useWizard.d.ts.map +1 -1
  40. package/lib/esm/hooks/useWizard.js +20 -6
  41. package/lib/esm/reducers/AIResponseConstNTypes.d.ts +17 -2
  42. package/lib/esm/reducers/AIResponseConstNTypes.d.ts.map +1 -1
  43. package/lib/esm/reducers/AIResponseConstNTypes.js +3 -0
  44. package/lib/esm/reducers/AIResponseReducer.d.ts +2 -0
  45. package/lib/esm/reducers/AIResponseReducer.d.ts.map +1 -1
  46. package/lib/esm/reducers/AIResponseReducer.js +17 -0
  47. package/lib/esm/reducers/CaseDiscussionTabReducer.js +1 -1
  48. package/lib/esm/reducers/RouteConstNTypes.d.ts.map +1 -1
  49. package/lib/esm/reducers/RouteConstNTypes.js +0 -1
  50. package/package.json +7 -7
@@ -8,26 +8,46 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import '@ifd-ui/ask-redhat-core/ask-redhat-core.css';
11
- import { Env } from '@cee-eng/hydrajs';
12
- import { AskRedHatChat, setAuthToken } from '@ifd-ui/ask-redhat-core';
11
+ import { Env, pcm } from '@cee-eng/hydrajs';
12
+ import { ARHEventName, AskRedHatChat, setAuthToken, } from '@ifd-ui/ask-redhat-core';
13
13
  import { Button, Card, CardBody, CardHeader, Tooltip } from '@patternfly/react-core';
14
14
  import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
15
15
  import { ErrorBoundary, LoadingDots } from '@rh-support/components';
16
16
  import { PreviousCaseTypes } from '@rh-support/utils';
17
+ import i18next from 'i18next';
17
18
  import isEmpty from 'lodash/isEmpty';
18
19
  import isEqual from 'lodash/isEqual';
19
- import React, { useContext, useRef } from 'react';
20
+ import React, { useCallback, useContext, useEffect, useRef } from 'react';
20
21
  import { Trans, useTranslation } from 'react-i18next';
21
- import { useAIResponseState } from '../../context/AIResponseContext';
22
+ import { useAIResponseDispatch, useAIResponseState } from '../../context/AIResponseContext';
22
23
  import { useCaseSelector } from '../../context/CaseContext';
23
24
  import { RouteContext } from '../../context/RouteContext';
25
+ import { SessionRestoreDispatchContext, SessionRestoreStateContext } from '../../context/SessionRestoreContext';
24
26
  import { TCStateContext } from '../../context/TopContentContext';
27
+ import { useAB } from '../../hooks/useAB';
28
+ import { setHasChunkReceived, updateConversationId } from '../../reducers/AIResponseReducer';
25
29
  import { appSourceId_ARH, excludedCaseTypesforARH } from '../../reducers/CaseConstNTypes';
30
+ import { AppRouteSections } from '../../reducers/RouteConstNTypes';
31
+ import { createOrUpdateSessionResources } from '../../reducers/SessionRestoreReducer';
26
32
  import { OpenShiftClusterId } from '../CaseManagement/OpenShiftClusterId';
27
33
  import ClusterRecommendations from '../Recommendations/ClusterRecommendations';
28
34
  import InsightsResults from '../Recommendations/InsightsResults';
35
+ import Recommendations from '../Recommendations/Recommendations';
29
36
  import Suggestions from '../Suggestions/Suggestions';
37
+ import { generateAIQuestion } from '../wizardLayout/WizardMain';
30
38
  import { AskRedHat } from './AskRedHat';
39
+ const { SessionResourceSource, SessionResourceVisibility } = pcm.preCase.session;
40
+ const getSessResFromARHSource = (source, visibilityStatus, rank = 1) => ({
41
+ visibilityStatus,
42
+ resourceEntityId: source.link || source.url,
43
+ url: source.link || source.url,
44
+ rank,
45
+ });
46
+ const getSessResFromAISources = (sources, visibilityStatus) => {
47
+ if (!sources || sources.length === 0)
48
+ return;
49
+ return sources.map((source, index) => getSessResFromARHSource(source, visibilityStatus, index + 1));
50
+ };
31
51
  const defaultProps = {
32
52
  initialIsEditing: false,
33
53
  required: false,
@@ -35,18 +55,28 @@ const defaultProps = {
35
55
  autoFocus: false,
36
56
  hideSaveCancel: false,
37
57
  aiServicesAvailable: false,
58
+ haveARHFieldsChanged: false,
38
59
  };
39
60
  function TroubleshootSection(props) {
40
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
61
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
41
62
  const { t } = useTranslation();
42
- const { aiServicesAvailable, isAIChatMode, setIsAIChatMode, onChatWithAIClick } = props;
43
- const refetchControlReady = useRef(null);
63
+ const { isVariationA } = useAB();
64
+ const { isAIChatMode } = props;
65
+ const lastDispatchedConversationIdRef = useRef(null);
66
+ const sourcesRef = useRef(null);
67
+ const clickedSourcesRef = useRef(new Set());
68
+ const engagementTimerRef = useRef(null);
69
+ const hasInteractionHappenedRef = useRef(false);
44
70
  const { topContentState: { topContent }, } = useContext(TCStateContext);
45
- const { routeState: { isCaseCreate }, } = useContext(RouteContext);
71
+ const { routeState: { isCaseCreate, activeSection }, } = useContext(RouteContext);
72
+ const { caseDetails } = useCaseSelector((state) => ({
73
+ caseDetails: state.caseDetails,
74
+ }), isEqual);
46
75
  const aiResponseState = useAIResponseState();
76
+ const aiResponseDispatch = useAIResponseDispatch();
47
77
  const session = window === null || window === void 0 ? void 0 : window.sessionjs;
48
78
  const keycloakSession = (_b = (_a = session === null || session === void 0 ? void 0 : session._state) === null || _a === void 0 ? void 0 : _a.keycloak) !== null && _b !== void 0 ? _b : null;
49
- const { product, version, isCreatingCase, caseType } = useCaseSelector((state) => ({
79
+ const { product, version, summary, issue, isCreatingCase, caseType } = useCaseSelector((state) => ({
50
80
  product: state.caseDetails.product,
51
81
  version: state.caseDetails.version,
52
82
  summary: state.caseDetails.summary,
@@ -54,35 +84,69 @@ function TroubleshootSection(props) {
54
84
  caseType: state.caseDetails.caseType,
55
85
  issue: state.caseDetails.issue,
56
86
  }), isEqual);
87
+ const { sessionRestore: { activeSessionId, sessionResourceTracking }, } = useContext(SessionRestoreStateContext);
88
+ const sessionRestoreDispatch = useContext(SessionRestoreDispatchContext);
57
89
  const canShowTopProducts = isEmpty(product);
58
90
  const canShowTopContent = !canShowTopProducts && ((_c = topContent === null || topContent === void 0 ? void 0 : topContent.data) === null || _c === void 0 ? void 0 : _c.length) > 0;
59
91
  const isNotAnIdea = caseType !== PreviousCaseTypes.FEATURE_ENHANCEMENT;
60
- const shouldShowARHUI = () => {
61
- // Check if the case type is allowed (not in the excluded list)
62
- const isCaseTypeAllowed = !excludedCaseTypesforARH.includes(caseType !== null && caseType !== void 0 ? caseType : '');
63
- // Check if user is not a secure support or confirmed stateside support user
64
- const isNotSecureOrStatesideUser = !props.isSecureSupport && !props.hasConfirmedStatesideSupport;
65
- // Check if AI services are available
66
- const isAIServicesAvailable = aiServicesAvailable;
67
- return isCaseTypeAllowed && isNotSecureOrStatesideUser && isAIServicesAvailable;
68
- };
69
- const handleInitialized = (success, error) => {
70
- var _a, _b;
71
- if (success) {
72
- console.log('Chat initialized successfully');
73
- try {
74
- if (!isEmpty((_a = aiResponseState.aiResponse) === null || _a === void 0 ? void 0 : _a.conversationId)) {
75
- (_b = refetchControlReady.current) === null || _b === void 0 ? void 0 : _b.refetch();
92
+ const clearEngagementTimer = useCallback(() => {
93
+ if (engagementTimerRef.current) {
94
+ clearTimeout(engagementTimerRef.current);
95
+ engagementTimerRef.current = null;
96
+ }
97
+ }, []);
98
+ // Call resource API with sources if available, otherwise create resource origin with payload only
99
+ const callResourceAPI = useCallback((sources, visibilityStatus) => {
100
+ if (!activeSessionId)
101
+ return;
102
+ const payload = JSON.stringify({ product, version, summary, issue });
103
+ if (sources && sources.length > 0) {
104
+ const sessionResources = visibilityStatus === SessionResourceVisibility.VISITED
105
+ ? sources.map((source, index) => getSessResFromARHSource(source, visibilityStatus, index + 1))
106
+ : getSessResFromAISources(sources, visibilityStatus);
107
+ createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.ASK_RED_HAT, sessionResources, payload);
108
+ }
109
+ else {
110
+ createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.ASK_RED_HAT, undefined, payload);
111
+ }
112
+ }, [activeSessionId, product, version, summary, issue, sessionRestoreDispatch, sessionResourceTracking]);
113
+ const handleARHEvent = useCallback((eventData) => {
114
+ // Enable "See more resources" button when first chunk is received
115
+ if (eventData.eventName === ARHEventName.AnswerReceived) {
116
+ aiResponseDispatch(setHasChunkReceived(true));
117
+ }
118
+ // If message sent with conversationId, call API immediately (engagement happened)
119
+ if (eventData.eventName === ARHEventName.MessageSent && isVariationA) {
120
+ const { conversationId } = eventData.payload;
121
+ if (conversationId !== undefined && conversationId !== null && conversationId !== '') {
122
+ clearEngagementTimer();
123
+ if (!hasInteractionHappenedRef.current) {
124
+ hasInteractionHappenedRef.current = true;
125
+ callResourceAPI(sourcesRef.current, SessionResourceVisibility.PRESENTED);
76
126
  }
77
127
  }
78
- catch (error) {
79
- console.error('Failed to refetch conversation:', error);
128
+ }
129
+ if (eventData.eventName === ARHEventName.SourcePresented) {
130
+ const { conversationId, sources } = eventData.payload;
131
+ if (sources && Array.isArray(sources)) {
132
+ sourcesRef.current = sources.map((source) => (Object.assign(Object.assign({}, source), { url: source.sourceUrl || source.url, link: source.sourceUrl || source.link })));
133
+ }
134
+ if (conversationId && conversationId !== lastDispatchedConversationIdRef.current) {
135
+ lastDispatchedConversationIdRef.current = conversationId;
136
+ aiResponseDispatch(updateConversationId(conversationId));
80
137
  }
81
138
  }
82
- else {
83
- console.error('Chat initialization failed:', error);
139
+ if (eventData.eventName === ARHEventName.SourceClicked && isVariationA) {
140
+ const { sourceUrl, sourceText } = eventData.payload;
141
+ if (!sourceUrl || clickedSourcesRef.current.has(sourceUrl))
142
+ return;
143
+ clickedSourcesRef.current.add(sourceUrl);
144
+ hasInteractionHappenedRef.current = true;
145
+ clearEngagementTimer();
146
+ const source = { url: sourceUrl, link: sourceUrl, sourceUrl, sourceText };
147
+ callResourceAPI([source], SessionResourceVisibility.VISITED);
84
148
  }
85
- };
149
+ }, [aiResponseDispatch, callResourceAPI, clearEngagementTimer, isVariationA]);
86
150
  const preprocessRequest = () => __awaiter(this, void 0, void 0, function* () {
87
151
  var _a;
88
152
  if (!keycloakSession) {
@@ -104,14 +168,42 @@ function TroubleshootSection(props) {
104
168
  throw error;
105
169
  }
106
170
  });
171
+ const detailedQuestion = generateAIQuestion(activeSection || '', caseDetails.product, caseDetails.version, caseDetails.summary, caseDetails.issue, caseDetails.caseType || '', i18next.language || 'en');
172
+ const latestUserMessage = isVariationA && ((_d = aiResponseState.aiResponse) === null || _d === void 0 ? void 0 : _d.conversationId) && props.haveARHFieldsChanged
173
+ ? detailedQuestion
174
+ : '';
175
+ const firstUserMessage = isVariationA && !((_e = aiResponseState.aiResponse) === null || _e === void 0 ? void 0 : _e.conversationId) ? detailedQuestion : '';
176
+ // Reset the flag when component unmounts
177
+ useEffect(() => {
178
+ return () => {
179
+ var _a;
180
+ (_a = props.resetARHFieldsChanged) === null || _a === void 0 ? void 0 : _a.call(props);
181
+ };
182
+ // eslint-disable-next-line react-hooks/exhaustive-deps
183
+ }, []);
184
+ // 10-second engagement timer - call API if no source clicked or message not sent by user
185
+ useEffect(() => {
186
+ if (aiResponseState.hasChunkReceived && isVariationA) {
187
+ engagementTimerRef.current = setTimeout(() => {
188
+ if (hasInteractionHappenedRef.current || clickedSourcesRef.current.size > 0) {
189
+ return;
190
+ }
191
+ callResourceAPI(sourcesRef.current, SessionResourceVisibility.PRESENTED);
192
+ engagementTimerRef.current = null;
193
+ }, 10000);
194
+ return clearEngagementTimer;
195
+ }
196
+ }, [aiResponseState.hasChunkReceived, isVariationA, callResourceAPI, clearEngagementTimer]);
107
197
  const initConfig = {
108
- packageVersion: (_d = window === null || window === void 0 ? void 0 : window.supportVersionInfo) === null || _d === void 0 ? void 0 : _d.packageVersion,
198
+ packageVersion: (_f = window === null || window === void 0 ? void 0 : window.supportVersionInfo) === null || _f === void 0 ? void 0 : _f.packageVersion,
109
199
  appSourceId: appSourceId_ARH,
110
200
  enableDebugLogging: false,
111
201
  headerTitle: isCaseCreate ? t('Resolve your issue now with AI insights') : t('Troubleshoot with AI insights'),
112
202
  appEnv: Env.getEnvName(),
113
203
  showWelcomeMessage: false,
114
- conversationId: ((_e = aiResponseState.aiResponse) === null || _e === void 0 ? void 0 : _e.conversationId) || undefined,
204
+ firstUserMessage: firstUserMessage,
205
+ conversationId: (_h = (_g = aiResponseState.aiResponse) === null || _g === void 0 ? void 0 : _g.conversationId) !== null && _h !== void 0 ? _h : '',
206
+ latestUserMessage: latestUserMessage,
115
207
  enableHeaderMenu: false,
116
208
  enableTheme: false,
117
209
  openLinkInNewTab: true,
@@ -122,8 +214,8 @@ function TroubleshootSection(props) {
122
214
  } })),
123
215
  tokenAuth: {
124
216
  auth: {
125
- userInfo: (_h = (_g = (_f = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _f === void 0 ? void 0 : _f.getToken) === null || _g === void 0 ? void 0 : _g.call(_f)) !== null && _h !== void 0 ? _h : {},
126
- authToken: (_k = (_j = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _j === void 0 ? void 0 : _j.getEncodedToken()) !== null && _k !== void 0 ? _k : '',
217
+ userInfo: (_l = (_k = (_j = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _j === void 0 ? void 0 : _j.getToken) === null || _k === void 0 ? void 0 : _k.call(_j)) !== null && _l !== void 0 ? _l : {},
218
+ authToken: (_o = (_m = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _m === void 0 ? void 0 : _m.getEncodedToken()) !== null && _o !== void 0 ? _o : '',
127
219
  },
128
220
  events: {
129
221
  preprocessRequest,
@@ -133,31 +225,45 @@ function TroubleshootSection(props) {
133
225
  },
134
226
  },
135
227
  },
136
- onInitialized: handleInitialized,
228
+ onARHEvent: handleARHEvent,
137
229
  onUnauthenticatedLogin: () => {
138
230
  var _a, _b;
139
231
  (_b = (_a = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _a === void 0 ? void 0 : _a.login) === null || _b === void 0 ? void 0 : _b.call(_a);
140
232
  },
141
- onForceRefetchConversation: (refetchControl) => {
142
- refetchControlReady.current = refetchControl;
143
- },
233
+ };
234
+ const shouldShowARHUI = () => {
235
+ if (isVariationA) {
236
+ return false;
237
+ }
238
+ // Check if the case type is allowed (not in the excluded list)
239
+ const isCaseTypeAllowed = !excludedCaseTypesforARH.includes(caseType !== null && caseType !== void 0 ? caseType : '');
240
+ // Check if user is not a secure support or confirmed stateside support user
241
+ const isNotSecureOrStatesideUser = !props.isSecureSupport && !props.hasConfirmedStatesideSupport;
242
+ // Check if AI services are available
243
+ const isAIServicesAvailable = props.aiServicesAvailable;
244
+ return isCaseTypeAllowed && isNotSecureOrStatesideUser && isAIServicesAvailable;
144
245
  };
145
246
  const handleChatWithAIClick = () => {
146
- setIsAIChatMode(true);
147
- onChatWithAIClick === null || onChatWithAIClick === void 0 ? void 0 : onChatWithAIClick();
247
+ var _a;
248
+ props.setIsAIChatMode(true);
249
+ (_a = props.onChatWithAIClick) === null || _a === void 0 ? void 0 : _a.call(props);
148
250
  };
149
251
  return (React.createElement(React.Fragment, null, isAIChatMode ? (React.createElement(React.Fragment, null,
150
252
  React.createElement(AskRedHatChat, { initConfig: initConfig }),
151
- React.createElement("div", { className: "fullscreen-chat-footer" }, isCaseCreate ? (React.createElement("span", null,
253
+ React.createElement("div", { className: "fullscreen-chat-footer" }, isVariationA && activeSection === AppRouteSections.RESOURCES ? (React.createElement(React.Fragment, null,
254
+ React.createElement("button", { onClick: props.onBack, className: "btn btn-app btn-open-white main-nav-button", type: "button" }, t('Go back')),
255
+ React.createElement("button", { onClick: () => props.setIsAIChatMode(false), className: "btn btn-app btn-primary main-nav-button", type: "button", disabled: !aiResponseState.hasChunkReceived }, t('See more resources')))) : isCaseCreate ? (React.createElement("span", null,
152
256
  React.createElement(Trans, { i18nKey: "<span>Return to</span> <button>case creation</button>", components: {
153
257
  span: React.createElement("span", { className: "return-to-case-text" }),
154
258
  button: (React.createElement(Button, { className: "return-to-case-btn", variant: "link", component: "a", onClick: () => props.setIsAIChatMode(false) })),
155
259
  } }))) : (React.createElement(Button, { onClick: () => props.setIsAIChatMode(false), variant: "link", className: "return-to-resources-btn" }, t('Back to resources')))))) : (React.createElement(React.Fragment, null,
156
260
  React.createElement("section", null,
157
- shouldShowARHUI() && React.createElement(AskRedHat, { onChatWithAIClick: handleChatWithAIClick }),
158
- !isCreatingCase && (React.createElement(OpenShiftClusterId, { className: "push-bottom", "data-tracking-id": "troubleshoot-section-openshift-cluster-id" })),
261
+ isVariationA ? (React.createElement("div", { className: "suggestions-result-section" },
262
+ React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading recommendations') } }, !isEmpty(version) && (React.createElement("div", { className: "common-suggestions" },
263
+ React.createElement(Recommendations, { routeProps: props.routeProps, userSeenRecommendations: props.userSeenRecommendations, userClickedNextonRecommendationsValue: props.userClickedNextonRecommendations, resultsRowRef: props.resultsRowRef })))))) : (shouldShowARHUI() && React.createElement(AskRedHat, { onChatWithAIClick: handleChatWithAIClick })),
264
+ !isVariationA && !isCreatingCase && (React.createElement(OpenShiftClusterId, { className: "push-bottom", "data-tracking-id": "troubleshoot-section-openshift-cluster-id" })),
159
265
  React.createElement(LoadingDots, { show: topContent.isFetching }),
160
- topContent.data.length === 0 && (React.createElement(Card, { id: "card", className: "pf-v6-u-mb-md" },
266
+ !isVariationA && topContent.data.length === 0 && (React.createElement(Card, { id: "card", className: "pf-v6-u-mb-md" },
161
267
  React.createElement(CardHeader, { id: "card-title" },
162
268
  React.createElement(Trans, { i18nKey: 'i18nKeyPopularSolutions' }, "Red Hat hand picked support articles"),
163
269
  React.createElement(Tooltip, { content: React.createElement("div", null,
@@ -1 +1 @@
1
- {"version":3,"file":"useIsSectionValid.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/useIsSectionValid.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAuB/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAMnE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,gBAAgB;;;;;EAmU9D"}
1
+ {"version":3,"file":"useIsSectionValid.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/useIsSectionValid.tsx"],"names":[],"mappings":"AAKA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAwB/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAMnE,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,gBAAgB;;;;;EAgR9D"}
@@ -18,6 +18,7 @@ import { useCaseSelector } from '../../context/CaseContext';
18
18
  import { RecommendationStateContext } from '../../context/RecommendationContext';
19
19
  import { RouteContext, useRouteDispatchContext } from '../../context/RouteContext';
20
20
  import { TCStateContext } from '../../context/TopContentContext';
21
+ import { useAB } from '../../hooks/useAB';
21
22
  import { CASE_DEATILS_ENVIRONMENT_LIMIT, CASE_REFERENCE_NUMBER_LIMIT, CONTACT_INFO_24X7_LIMIT, HOSTNAME_LENGTH_LIMIT, ISSUE_SUMMARY_LENGTH_LIMIT, KTQUESTION_MAX_LIMIT, TITLE_SUMMARY_LENGTH_LIMIT, } from '../../reducers/CaseConstNTypes';
22
23
  import { isCaseInformationSectionValid, isCaseManagementStateValid, isCaseStateValid, isClusterIDValid, isIdeaCaseStateValid, } from '../../reducers/CaseHelpers';
23
24
  import { AppRouteSections } from '../../reducers/RouteConstNTypes';
@@ -25,7 +26,8 @@ import { setNoValidEntitlement } from '../../reducers/RouteReducer';
25
26
  import { AttachmentStateContext } from './fileUpload/reducer/AttachmentReducerContext';
26
27
  export function useIsSectionValid(sectionName) {
27
28
  var _a, _b;
28
- const { caseState, caseType, product, version, contactSSOName, accountNumber, summary, hostname, contactInfo24x7, alternateId, selectedAccountDetails, issue, environment, timeFramesAndUrgency, periodicityOfIssue, ABTestVariation, ssoUsername, manageSupportCases, } = useCaseSelector((state) => ({
29
+ const { isVariationA } = useAB();
30
+ const { caseState, caseType, product, version, contactSSOName, accountNumber, summary, hostname, contactInfo24x7, alternateId, selectedAccountDetails, issue, environment, timeFramesAndUrgency, periodicityOfIssue, ssoUsername, manageSupportCases, } = useCaseSelector((state) => ({
29
31
  caseState: state,
30
32
  caseType: state.caseDetails.caseType,
31
33
  product: state.caseDetails.product,
@@ -41,7 +43,6 @@ export function useIsSectionValid(sectionName) {
41
43
  environment: state.caseDetails.environment,
42
44
  timeFramesAndUrgency: state.caseDetails.timeFramesAndUrgency,
43
45
  periodicityOfIssue: state.caseDetails.periodicityOfIssue,
44
- ABTestVariation: state.ABTestVariation,
45
46
  ssoUsername: state.selectedOwner.data.ssoUsername,
46
47
  manageSupportCases: state.selectedOwner.data.manageSupportCases,
47
48
  }), isEqual);
@@ -66,8 +67,6 @@ export function useIsSectionValid(sectionName) {
66
67
  fetchContactDetails();
67
68
  }, [ssoUsername, routeDispatch]);
68
69
  //&seSessionId=8e8960ac-680b-443e-bf67-9e13f2acd64e
69
- const isATestvariation = ABTestVariation === 'A';
70
- const isBTestvariation = ABTestVariation === 'B' || isEmpty(ABTestVariation);
71
70
  const { routeState: { isCaseCreate }, } = useContext(RouteContext);
72
71
  const { globalMetadataState: { allProducts, loggedInUserJwtToken }, } = useContext(GlobalMetadataStateContext);
73
72
  const { topContentState: { topContent }, } = useContext(TCStateContext);
@@ -92,54 +91,34 @@ export function useIsSectionValid(sectionName) {
92
91
  !isEmpty(contactSSOName) &&
93
92
  !selectedAccountDetails.data.subscriptionAbuse &&
94
93
  (manageSupportCases !== null && manageSupportCases !== void 0 ? manageSupportCases : true) &&
95
- (isEntitlement !== null && isEntitlement !== void 0 ? isEntitlement : true);
96
- if (isATestvariation) {
97
- isValid = isValid && !isEmpty(product) && !isEmpty(version);
98
- }
94
+ (isEntitlement !== null && isEntitlement !== void 0 ? isEntitlement : true) &&
95
+ !isEmpty(product) &&
96
+ !isEmpty(version);
99
97
  return isValid;
100
98
  };
101
99
  const isSummarizeSectionValid = () => {
102
- if (isBTestvariation) {
103
- let isValid = !allProducts.isFetching &&
104
- !allProducts.isError &&
105
- !topContent.isFetching &&
106
- !recommendationState.isLoadingRecommendations &&
107
- (summary === null || summary === void 0 ? void 0 : summary.length) <= TITLE_SUMMARY_LENGTH_LIMIT &&
108
- (issue === null || issue === void 0 ? void 0 : issue.length) <= ISSUE_SUMMARY_LENGTH_LIMIT &&
109
- !isEmpty(product) &&
110
- !isEmpty(version) &&
111
- !isEmpty(summary) &&
112
- !isEmpty(issue);
113
- return isValid;
114
- }
115
- if (isATestvariation) {
116
- let isValid = !allProducts.isFetching &&
117
- !allProducts.isError &&
118
- !topContent.isFetching &&
119
- !recommendationState.isLoadingRecommendations &&
120
- (summary === null || summary === void 0 ? void 0 : summary.length) <= TITLE_SUMMARY_LENGTH_LIMIT &&
121
- (issue === null || issue === void 0 ? void 0 : issue.length) <= ISSUE_SUMMARY_LENGTH_LIMIT &&
122
- !isEmpty(summary) &&
123
- !isEmpty(issue);
124
- return isValid;
125
- }
100
+ let isValid = !allProducts.isFetching &&
101
+ !allProducts.isError &&
102
+ !topContent.isFetching &&
103
+ !recommendationState.isLoadingRecommendations &&
104
+ (summary === null || summary === void 0 ? void 0 : summary.length) <= TITLE_SUMMARY_LENGTH_LIMIT &&
105
+ (issue === null || issue === void 0 ? void 0 : issue.length) <= ISSUE_SUMMARY_LENGTH_LIMIT &&
106
+ !isEmpty(summary) &&
107
+ !isEmpty(issue);
126
108
  if (isCaseCreate) {
127
109
  //because on the summarize page for troubleshoot flow we have only product version and owner
128
- let isValid = !allProducts.isFetching &&
129
- !allProducts.isError &&
130
- // !topContent.isFetching &&
131
- // !recommendationState.isLoadingRecommendations &&
132
- // summary!?.length <= TITLE_SUMMARY_LENGTH_LIMIT &&
133
- // issue!?.length <= ISSUE_SUMMARY_LENGTH_LIMIT &&
134
- !isEmpty(product) &&
135
- !isEmpty(accountNumber) &&
136
- !isEmpty(contactSSOName) &&
137
- !isEmpty(version);
138
- return isValid;
110
+ isValid =
111
+ !allProducts.isFetching &&
112
+ !allProducts.isError &&
113
+ !isEmpty(product) &&
114
+ !isEmpty(accountNumber) &&
115
+ !isEmpty(contactSSOName) &&
116
+ !isEmpty(version);
139
117
  }
140
118
  else if (!isCaseCreate) {
141
119
  return !isEmpty(product) && !isEmpty(version) && !isEmpty(accountNumber) && !isEmpty(contactSSOName);
142
120
  }
121
+ return isValid;
143
122
  };
144
123
  const isCaseConfigurationSectionValid = () => {
145
124
  const hasContactInfo24x7ValidLength = contactInfo24x7
@@ -151,30 +130,12 @@ export function useIsSectionValid(sectionName) {
151
130
  hasAlternateCaseIdValidLength);
152
131
  };
153
132
  const isResourcesSectionValid = () => {
154
- var _a, _b;
155
- if (isBTestvariation) {
156
- //if we are in the new experience and user is troubleshoot we give them those validity fields
157
- if (!isCaseCreate) {
158
- let isValid = !allProducts.isFetching &&
159
- !allProducts.isError &&
160
- !topContent.isFetching &&
161
- !recommendationState.isLoadingRecommendations &&
162
- (summary === null || summary === void 0 ? void 0 : summary.length) <= TITLE_SUMMARY_LENGTH_LIMIT &&
163
- (issue === null || issue === void 0 ? void 0 : issue.length) <= ISSUE_SUMMARY_LENGTH_LIMIT &&
164
- !isEmpty(product) &&
165
- !isEmpty(version) &&
166
- !isEmpty(summary) &&
167
- !isEmpty(issue) &&
168
- isEntitlement === true &&
169
- isClusterIDValid(caseState, (_a = allProducts.data) === null || _a === void 0 ? void 0 : _a.productsResult);
170
- return isValid;
171
- }
172
- }
133
+ var _a;
173
134
  // don't check for entitled product if user is on search intent flow
174
135
  const isEntitledProductLocal = isSearchIntent ? true : isEntitledProduct;
175
- return (!recommendationState.isLoadingRecommendations &&
176
- isEntitledProductLocal &&
177
- isClusterIDValid(caseState, (_b = allProducts.data) === null || _b === void 0 ? void 0 : _b.productsResult));
136
+ // Skip cluster ID validation for Variant A
137
+ const clusterIdValid = isVariationA ? true : isClusterIDValid(caseState, (_a = allProducts.data) === null || _a === void 0 ? void 0 : _a.productsResult);
138
+ return !recommendationState.isLoadingRecommendations && isEntitledProductLocal && clusterIdValid;
178
139
  };
179
140
  const isReviewSectionValid = () => {
180
141
  var _a;
@@ -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;AAQzC,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,qBAuDjC;kBAvDQ,WAAW;;;AAyDpB,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;AAMvD,OAAO,EAGH,eAAe,EAIlB,MAAM,iCAAiC,CAAC;AASzC,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,qBAgEjC;kBAhEQ,WAAW;;;AAkEpB,eAAe,WAAW,CAAC"}
@@ -5,7 +5,9 @@ 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, showSideBarClusterIdRuleWidgetSections, showSideBarEARuleWidgetSections, showSideBarEARuleWidgetSectionsExperienceA, showSideBarFileRecommendationSections, } from '../../reducers/RouteConstNTypes';
8
+ import { TCStateContext } from '../../context/TopContentContext';
9
+ import { useAB } from '../../hooks/useAB';
10
+ import { AppRouteSections, hideFileUploadSidebarWidgetSections, showSideBarClusterIdRuleWidgetSections, showSideBarEARuleWidgetSectionsExperienceA, showSideBarFileRecommendationSections, } from '../../reducers/RouteConstNTypes';
9
11
  import { FileDiag } from '../CaseInformation/FileDiag';
10
12
  import { CveSidebar } from '../Cve/CveSidebar';
11
13
  import { AsideResults } from '../Recommendations/AsideResults';
@@ -13,28 +15,34 @@ import ClusterRecommendations from '../Recommendations/ClusterRecommendations';
13
15
  import { EARuleWidget } from '../Recommendations/EARules/EARuleWidget';
14
16
  import InsightsResults from '../Recommendations/InsightsResults';
15
17
  import { SessionRestore } from '../SessionRestore';
18
+ import TopContentSidebar from '../Suggestions/TopContentSidebar';
16
19
  const defaultProps = {};
17
20
  function WizardAside(props) {
21
+ const { isVariationA } = useAB();
18
22
  const { routeState: { activeSection, isCaseCreate }, } = useContext(RouteContext);
23
+ const { topContentState: { topContent }, } = useContext(TCStateContext);
19
24
  const canAddAttachments = ability.can(resourceActions.PATCH, resources.CASE_CREATE, CaseListFields.ATTACHMENTS);
20
- const { isCreatingCase, caseType, isCveModalOpened, ABTestVariation } = useCaseSelector((state) => ({
25
+ const { isCreatingCase, caseType, isCveModalOpened } = useCaseSelector((state) => ({
21
26
  isCreatingCase: state.isCreatingCase,
22
27
  caseType: state.caseDetails.caseType,
23
28
  isCveModalOpened: state.isCveModalOpened,
24
- ABTestVariation: state.ABTestVariation,
25
29
  }), isEqual);
26
- const isATestvariation = ABTestVariation === 'A';
27
30
  const isIdea = caseType === PreviousCaseTypes.FEATURE_ENHANCEMENT;
28
31
  const canUseSessionManagement = ability.can(resourceActions.CREATE, resources.SESSION_TRACKING);
29
32
  const canShowFileUploadWidget = () => canAddAttachments &&
30
33
  !props.isAttachmentUploadModalOpen &&
31
34
  !isUndefined(activeSection) &&
32
35
  !hideFileUploadSidebarWidgetSections.includes(activeSection);
33
- const canShowEARuleWidget = isATestvariation
36
+ const canShowEARuleWidget = activeSection
34
37
  ? showSideBarEARuleWidgetSectionsExperienceA.includes(activeSection)
35
- : showSideBarEARuleWidgetSections.includes(activeSection);
36
- const canShowClusterIdReportWidget = showSideBarClusterIdRuleWidgetSections.includes(activeSection);
37
- const canShowFileRecommendationSectionsWidget = showSideBarFileRecommendationSections.includes(activeSection);
38
+ : false;
39
+ const canShowClusterIdReportWidget = activeSection
40
+ ? showSideBarClusterIdRuleWidgetSections.includes(activeSection)
41
+ : false;
42
+ const canShowFileRecommendationSectionsWidget = activeSection
43
+ ? showSideBarFileRecommendationSections.includes(activeSection)
44
+ : false;
45
+ const showTopContentSidebar = isVariationA && activeSection === AppRouteSections.RESOURCES && topContent.data.length === 0;
38
46
  return (React.createElement("aside", null,
39
47
  React.createElement("section", { className: "grid-aside-content" },
40
48
  canUseSessionManagement && !isCreatingCase && activeSection !== AppRouteSections.SUBMIT_CASE && (React.createElement(SessionRestore, { routeProps: props.routeProps })),
@@ -46,7 +54,8 @@ function WizardAside(props) {
46
54
  canShowEARuleWidget && React.createElement(EARuleWidget, null),
47
55
  !(isIdea && activeSection === 'submit-case') && (React.createElement(AsideResults, { routeProps: props.routeProps, className: "pf-v6-u-mb-md" })),
48
56
  canShowFileRecommendationSectionsWidget && React.createElement(InsightsResults, { isDisplayOnMain: true }),
49
- React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v6-u-mb-md" }))));
57
+ React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v6-u-mb-md" }),
58
+ showTopContentSidebar && React.createElement(TopContentSidebar, null))));
50
59
  }
51
60
  WizardAside.defaultProps = defaultProps;
52
61
  export default WizardAside;
@@ -1 +1 @@
1
- {"version":3,"file":"WizardMain.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardMain.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAqD,MAAM,OAAO,CAAC;AAE3G,OAAO,EAAS,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAW9D,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAcpF,eAAO,MAAM,iBAAiB,aAAc,MAAM,KAAG,MAEpD,CAAC;AAEF,eAAO,MAAM,sBAAsB,kBAAmB,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAG,MAqB9F,CAAC;AAGF,eAAO,MAAM,kBAAkB,kBACZ,MAAM,WACZ,MAAM,GAAG,SAAS,WAClB,MAAM,GAAG,SAAS,WAClB,MAAM,GAAG,SAAS,SACpB,MAAM,GAAG,SAAS,YACf,MAAM,QACV,MAAM,KACb,MAwCF,CAAC;AACF,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,qBAAqB,EAAE,CAAC,cAAc,EAAE,OAAO,KAAK,IAAI,CAAC;IACzD,mBAAmB,EAAE,CAAC,gCAAgC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzE,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,qBA4WhC;AACD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"WizardMain.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardMain.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAkE,MAAM,OAAO,CAAC;AAExH,OAAO,EAAS,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAY9D,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAcpF,eAAO,MAAM,iBAAiB,aAAc,MAAM,KAAG,MAEpD,CAAC;AAEF,eAAO,MAAM,sBAAsB,kBAAmB,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAG,MAqB9F,CAAC;AAGF,eAAO,MAAM,kBAAkB,kBACZ,MAAM,WACZ,MAAM,GAAG,SAAS,WAClB,MAAM,GAAG,SAAS,WAClB,MAAM,GAAG,SAAS,SACpB,MAAM,GAAG,SAAS,YACf,MAAM,QACV,MAAM,KACb,MAwCF,CAAC;AACF,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,qBAAqB,EAAE,CAAC,cAAc,EAAE,OAAO,KAAK,IAAI,CAAC;IACzD,mBAAmB,EAAE,CAAC,gCAAgC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzE,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,iBAAS,UAAU,CAAC,KAAK,EAAE,MAAM,qBA8ZhC;AACD,eAAe,UAAU,CAAC"}