@rh-support/troubleshoot 2.6.134 → 2.6.136

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.
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export default function EmptyTopContentSidebar(): React.JSX.Element;
3
+ //# sourceMappingURL=EmptyTopContentSidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyTopContentSidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/Suggestions/EmptyTopContentSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C,MAAM,CAAC,OAAO,UAAU,sBAAsB,sBA2C7C"}
@@ -5,7 +5,7 @@ import React, { useContext } from 'react';
5
5
  import { Trans, useTranslation } from 'react-i18next';
6
6
  import { useCaseSelector } from '../../context/CaseContext';
7
7
  import { TCStateContext } from '../../context/TopContentContext';
8
- export default function TopContentSidebar() {
8
+ export default function EmptyTopContentSidebar() {
9
9
  const { t } = useTranslation();
10
10
  const { topContentState: { topContent }, } = useContext(TCStateContext);
11
11
  const { version } = useCaseSelector((state) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"AskRedHat.d.ts","sourceRoot":"","sources":["../../../../src/components/TroubleshootSection/AskRedHat.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAkCvE,UAAU,MAAM;IACZ,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,eAAO,MAAM,SAAS,0BAA2B,MAAM,sBAwdtD,CAAC"}
1
+ {"version":3,"file":"AskRedHat.d.ts","sourceRoot":"","sources":["../../../../src/components/TroubleshootSection/AskRedHat.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAmCvE,UAAU,MAAM;IACZ,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,eAAO,MAAM,SAAS,0BAA2B,MAAM,sBA2ftD,CAAC"}
@@ -26,6 +26,7 @@ import { useParseRuleMarkdown } from '../../hooks/useParseRuleMarkdown';
26
26
  import { addSubmittedFeedbackType, clearSubmittedFeedbackTypes } from '../../reducers/AIResponseReducer';
27
27
  import { appSourceId_ARH } from '../../reducers/CaseConstNTypes';
28
28
  import { createOrUpdateSessionResources } from '../../reducers/SessionRestoreReducer';
29
+ import { calculateEngagementWindow, DEFAULT_ENGAGEMENT_WINDOW } from '../../utils/engagementUtils';
29
30
  import { CollapseIcon } from './icons/CollapseIcon';
30
31
  import { StarIcon } from './icons/StarIcon';
31
32
  import ResponseActions from './ResponseActions';
@@ -55,6 +56,9 @@ export const AskRedHat = ({ onChatWithAIClick }) => {
55
56
  const contentRef = useRef(null);
56
57
  const storedMessageIdRef = useRef(undefined);
57
58
  const aiResponseDispatch = useAIResponseDispatch();
59
+ const engagementTimerRef = useRef(null);
60
+ const engagementWindowRef = useRef(DEFAULT_ENGAGEMENT_WINDOW);
61
+ const hasEngagementTimerStartedRef = useRef(false);
58
62
  const { routeState: { isCaseCreate, activeSection }, } = useContext(RouteContext);
59
63
  const { sessionRestore: { activeSessionId, sessionResourceTracking, previousSessions }, } = useContext(SessionRestoreStateContext);
60
64
  const sessionRestoreDispatch = useContext(SessionRestoreDispatchContext);
@@ -85,20 +89,27 @@ export const AskRedHat = ({ onChatWithAIClick }) => {
85
89
  if (isExpanded && contentRef.current) {
86
90
  contentRef.current.scrollTop = 0;
87
91
  }
88
- if (!isExpanded) {
89
- const payload = JSON.stringify({
90
- product,
91
- version,
92
- summary,
93
- issue,
94
- });
95
- const sessionResources = getSessResFromAISources(sources, SessionResourceVisibility.PRESENTED);
96
- createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.ASK_RED_HAT, sessionResources, payload);
97
- }
98
92
  setIsExpanded((prev) => !prev);
99
93
  };
94
+ const clearEngagementTimer = () => {
95
+ if (engagementTimerRef.current) {
96
+ clearTimeout(engagementTimerRef.current);
97
+ engagementTimerRef.current = null;
98
+ }
99
+ };
100
+ const callResourceAPI = (sources, visibilityStatus) => {
101
+ const payload = JSON.stringify({
102
+ product,
103
+ version,
104
+ summary,
105
+ issue,
106
+ });
107
+ const sessionResources = getSessResFromAISources(sources, visibilityStatus);
108
+ createOrUpdateSessionResources(sessionRestoreDispatch, activeSessionId, sessionResourceTracking, SessionResourceSource.ASK_RED_HAT, sessionResources, payload);
109
+ };
100
110
  const handleChatWithAIClick = () => __awaiter(void 0, void 0, void 0, function* () {
101
111
  var _a;
112
+ clearEngagementTimer();
102
113
  onChatWithAIClick === null || onChatWithAIClick === void 0 ? void 0 : onChatWithAIClick();
103
114
  if (!!conversationId) {
104
115
  dtmTrackEventAskRedhat(conversationId, appSourceId_ARH);
@@ -113,6 +124,7 @@ export const AskRedHat = ({ onChatWithAIClick }) => {
113
124
  const handleSourceClick = (source, index) => () => {
114
125
  if (!source || !activeSessionId)
115
126
  return;
127
+ clearEngagementTimer();
116
128
  const payload = JSON.stringify({
117
129
  product,
118
130
  version,
@@ -125,6 +137,22 @@ export const AskRedHat = ({ onChatWithAIClick }) => {
125
137
  };
126
138
  const aiResponse = aiResponseState.aiResponse;
127
139
  const messageId = aiResponse === null || aiResponse === void 0 ? void 0 : aiResponse.messageId;
140
+ // Calculate engagement window and start timer when streaming is complete
141
+ useEffect(() => {
142
+ if (!aiResponseState.isStreaming && (aiResponse === null || aiResponse === void 0 ? void 0 : aiResponse.answer)) {
143
+ engagementWindowRef.current = calculateEngagementWindow(aiResponse.answer, true);
144
+ hasEngagementTimerStartedRef.current = true;
145
+ clearEngagementTimer();
146
+ engagementTimerRef.current = setTimeout(() => {
147
+ callResourceAPI(sources, SessionResourceVisibility.PRESENTED);
148
+ engagementTimerRef.current = null;
149
+ }, engagementWindowRef.current);
150
+ }
151
+ return () => {
152
+ clearEngagementTimer();
153
+ };
154
+ // eslint-disable-next-line react-hooks/exhaustive-deps
155
+ }, [aiResponseState.isStreaming, aiResponse === null || aiResponse === void 0 ? void 0 : aiResponse.answer]);
128
156
  const currentSessionItem = previousSessions.data[activeSessionId];
129
157
  const conversationId = (_d = currentSessionItem === null || currentSessionItem === void 0 ? void 0 : currentSessionItem.session) === null || _d === void 0 ? void 0 : _d.conversationId;
130
158
  useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"TroubleshootSection.d.ts","sourceRoot":"","sources":["../../../../src/components/TroubleshootSection/TroubleshootSection.tsx"],"names":[],"mappings":"AAAA,OAAO,6CAA6C,CAAC;AAkBrD,OAAO,KAAqD,MAAM,OAAO,CAAC;AAE1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAUvD,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAyBpF,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,CAAC,EAAE,OAAO,CAAC;IAC3C,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7D,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC1D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC;AAWD,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBAmZzC;kBAnZQ,mBAAmB;;;AAsZ5B,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"TroubleshootSection.d.ts","sourceRoot":"","sources":["../../../../src/components/TroubleshootSection/TroubleshootSection.tsx"],"names":[],"mappings":"AAAA,OAAO,6CAA6C,CAAC;AAkBrD,OAAO,KAA+D,MAAM,OAAO,CAAC;AAEpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAUvD,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AA0BpF,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,CAAC,EAAE,OAAO,CAAC;IAC3C,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7D,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC1D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;CACnC;AAWD,iBAAS,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBAyazC;kBAzaQ,mBAAmB;;;AA4a5B,eAAe,mBAAmB,CAAC"}
@@ -17,7 +17,7 @@ import { PreviousCaseTypes } from '@rh-support/utils';
17
17
  import i18next from 'i18next';
18
18
  import isEmpty from 'lodash/isEmpty';
19
19
  import isEqual from 'lodash/isEqual';
20
- import React, { useCallback, useContext, useEffect, useRef } from 'react';
20
+ import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
21
21
  import { Trans, useTranslation } from 'react-i18next';
22
22
  import { useAIResponseDispatch, useAIResponseState } from '../../context/AIResponseContext';
23
23
  import { useCaseSelector } from '../../context/CaseContext';
@@ -29,6 +29,7 @@ import { setHasChunkReceived, updateConversationId } from '../../reducers/AIResp
29
29
  import { appSourceId_ARH, excludedCaseTypesforARH } from '../../reducers/CaseConstNTypes';
30
30
  import { AppRouteSections } from '../../reducers/RouteConstNTypes';
31
31
  import { createOrUpdateSessionResources } from '../../reducers/SessionRestoreReducer';
32
+ import { calculateEngagementWindow, DEFAULT_ENGAGEMENT_WINDOW } from '../../utils/engagementUtils';
32
33
  import { OpenShiftClusterId } from '../CaseManagement/OpenShiftClusterId';
33
34
  import ClusterRecommendations from '../Recommendations/ClusterRecommendations';
34
35
  import InsightsResults from '../Recommendations/InsightsResults';
@@ -67,6 +68,8 @@ function TroubleshootSection(props) {
67
68
  const clickedSourcesRef = useRef(new Set());
68
69
  const engagementTimerRef = useRef(null);
69
70
  const hasInteractionHappenedRef = useRef(false);
71
+ const engagementWindowRef = useRef(DEFAULT_ENGAGEMENT_WINDOW);
72
+ const [hasAnswerReceived, setHasAnswerReceived] = useState(false);
70
73
  const { topContentState: { topContent }, } = useContext(TCStateContext);
71
74
  const { routeState: { isCaseCreate, activeSection }, } = useContext(RouteContext);
72
75
  const { caseDetails } = useCaseSelector((state) => ({
@@ -146,6 +149,23 @@ function TroubleshootSection(props) {
146
149
  const source = { url: sourceUrl, link: sourceUrl, sourceUrl, sourceText };
147
150
  callResourceAPI([source], SessionResourceVisibility.VISITED);
148
151
  }
152
+ // Count characters from DOM when answer is fully received
153
+ if (eventData.eventName === ARHEventName.AnswerReceived) {
154
+ setTimeout(() => {
155
+ const allMessageContainers = document.querySelectorAll('.pf-chatbot__message-and-actions');
156
+ const messageContainer = allMessageContainers[allMessageContainers.length - 1];
157
+ if (!messageContainer)
158
+ return;
159
+ const excludedSelectors = ['.pf-chatbot__response-actions', '.pf-chatbot__source'];
160
+ const trimmedText = Array.from(messageContainer.children)
161
+ .filter((child) => !excludedSelectors.some((selector) => child.matches(selector)))
162
+ .map((child) => child.textContent || '')
163
+ .join(' ')
164
+ .trim();
165
+ engagementWindowRef.current = calculateEngagementWindow(trimmedText, false);
166
+ setHasAnswerReceived(true);
167
+ }, 100);
168
+ }
149
169
  }, [aiResponseDispatch, callResourceAPI, clearEngagementTimer, isVariationA]);
150
170
  const preprocessRequest = () => __awaiter(this, void 0, void 0, function* () {
151
171
  var _a;
@@ -181,19 +201,19 @@ function TroubleshootSection(props) {
181
201
  };
182
202
  // eslint-disable-next-line react-hooks/exhaustive-deps
183
203
  }, []);
184
- // 10-second engagement timer - call API if no source clicked or message not sent by user
204
+ // Dynamic engagement timer - call API if no source clicked or message not sent by user
185
205
  useEffect(() => {
186
- if (aiResponseState.hasChunkReceived && isVariationA) {
206
+ if (hasAnswerReceived && isVariationA) {
187
207
  engagementTimerRef.current = setTimeout(() => {
188
208
  if (hasInteractionHappenedRef.current || clickedSourcesRef.current.size > 0) {
189
209
  return;
190
210
  }
191
211
  callResourceAPI(sourcesRef.current, SessionResourceVisibility.PRESENTED);
192
212
  engagementTimerRef.current = null;
193
- }, 10000);
213
+ }, engagementWindowRef.current);
194
214
  return clearEngagementTimer;
195
215
  }
196
- }, [aiResponseState.hasChunkReceived, isVariationA, callResourceAPI, clearEngagementTimer]);
216
+ }, [hasAnswerReceived, isVariationA, callResourceAPI, clearEngagementTimer]);
197
217
  const initConfig = {
198
218
  packageVersion: (_f = window === null || window === void 0 ? void 0 : window.supportVersionInfo) === null || _f === void 0 ? void 0 : _f.packageVersion,
199
219
  appSourceId: appSourceId_ARH,
@@ -271,7 +291,7 @@ function TroubleshootSection(props) {
271
291
  React.createElement(InfoCircleIcon, { className: "pf-v6-u-ml-sm", "aria-label": "More info about how support articles are matched" }))),
272
292
  React.createElement(CardBody, { "aria-label": t('No recommendations for this product'), className: "file-recs-no-recommendation pf-v6-u-mt-md" },
273
293
  React.createElement(Trans, null, "No recommendations for this product")))),
274
- React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading suggestions') } }, canShowTopContent && !isEmpty(version) && React.createElement(Suggestions, null)),
294
+ React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading suggestions') } }, canShowTopContent && !isEmpty(version) && !isVariationA && React.createElement(Suggestions, null)),
275
295
  !isCreatingCase && React.createElement(ClusterRecommendations, { className: "pf-v6-u-mt-lg" })),
276
296
  React.createElement("section", { className: "pf-v6-u-mt-lg" }, isNotAnIdea && (React.createElement(InsightsResults, { isDisplayOnMain: true, "data-tracking-id": "troubleshoot-section-file-recs" })))))));
277
297
  }
@@ -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;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"}
1
+ {"version":3,"file":"WizardAside.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardAside.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,EAGH,eAAe,EAIlB,MAAM,iCAAiC,CAAC;AAUzC,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,2BAA2B,EAAE,OAAO,CAAC;CACxC;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,qBAoEjC;kBApEQ,WAAW;;;AAsEpB,eAAe,WAAW,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { ability, CaseListFields, resourceActions, resources } from '@rh-support/user-permissions';
2
2
  import { PreviousCaseTypes } from '@rh-support/utils';
3
+ import isEmpty from 'lodash/isEmpty';
3
4
  import isEqual from 'lodash/isEqual';
4
5
  import isUndefined from 'lodash/isUndefined';
5
6
  import React, { useContext } from 'react';
@@ -15,17 +16,19 @@ import ClusterRecommendations from '../Recommendations/ClusterRecommendations';
15
16
  import { EARuleWidget } from '../Recommendations/EARules/EARuleWidget';
16
17
  import InsightsResults from '../Recommendations/InsightsResults';
17
18
  import { SessionRestore } from '../SessionRestore';
18
- import TopContentSidebar from '../Suggestions/TopContentSidebar';
19
+ import EmptyTopContentSidebar from '../Suggestions/EmptyTopContentSidebar';
20
+ import Suggestions from '../Suggestions/Suggestions';
19
21
  const defaultProps = {};
20
22
  function WizardAside(props) {
21
23
  const { isVariationA } = useAB();
22
24
  const { routeState: { activeSection, isCaseCreate }, } = useContext(RouteContext);
23
25
  const { topContentState: { topContent }, } = useContext(TCStateContext);
24
26
  const canAddAttachments = ability.can(resourceActions.PATCH, resources.CASE_CREATE, CaseListFields.ATTACHMENTS);
25
- const { isCreatingCase, caseType, isCveModalOpened } = useCaseSelector((state) => ({
27
+ const { isCreatingCase, caseType, isCveModalOpened, version } = useCaseSelector((state) => ({
26
28
  isCreatingCase: state.isCreatingCase,
27
29
  caseType: state.caseDetails.caseType,
28
30
  isCveModalOpened: state.isCveModalOpened,
31
+ version: state.caseDetails.version,
29
32
  }), isEqual);
30
33
  const isIdea = caseType === PreviousCaseTypes.FEATURE_ENHANCEMENT;
31
34
  const canUseSessionManagement = ability.can(resourceActions.CREATE, resources.SESSION_TRACKING);
@@ -42,6 +45,7 @@ function WizardAside(props) {
42
45
  const canShowFileRecommendationSectionsWidget = activeSection
43
46
  ? showSideBarFileRecommendationSections.includes(activeSection)
44
47
  : false;
48
+ const showSuggestionsSidebar = isVariationA && activeSection === AppRouteSections.RESOURCES && topContent.data.length > 0 && !isEmpty(version);
45
49
  const showTopContentSidebar = isVariationA && activeSection === AppRouteSections.RESOURCES && topContent.data.length === 0;
46
50
  return (React.createElement("aside", null,
47
51
  React.createElement("section", { className: "grid-aside-content" },
@@ -55,7 +59,8 @@ function WizardAside(props) {
55
59
  !(isIdea && activeSection === 'submit-case') && (React.createElement(AsideResults, { routeProps: props.routeProps, className: "pf-v6-u-mb-md" })),
56
60
  canShowFileRecommendationSectionsWidget && React.createElement(InsightsResults, { isDisplayOnMain: true }),
57
61
  React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v6-u-mb-md" }),
58
- showTopContentSidebar && React.createElement(TopContentSidebar, null))));
62
+ showSuggestionsSidebar && React.createElement(Suggestions, null),
63
+ showTopContentSidebar && React.createElement(EmptyTopContentSidebar, null))));
59
64
  }
60
65
  WizardAside.defaultProps = defaultProps;
61
66
  export default WizardAside;
@@ -265,10 +265,10 @@ function WizardMain(props) {
265
265
  RouteUtils.navigateToSection(props.routeProps, `${props.routeProps.location.pathname}/${step.id}`, false);
266
266
  };
267
267
  const onBack = (step, prevStep) => {
268
- // isLoadingRecommendations needs to be set to false when going back TO the summary step
268
+ // isLoadingRecommendations needs to be set to false when going back TO the summary/troubleshoot step
269
269
  // because it can cause the next button to be permanently disabled if the debounce is not called
270
270
  // before going back a step. This can be caused if navigating quickly to then away from the recommendations page.
271
- if (step.id === AppRouteSections.SUMMARIZE) {
271
+ if (step.id === AppRouteSections.SUMMARIZE || step.id === AppRouteSections.TROUBLESHOOT) {
272
272
  recommendationDispatch({
273
273
  type: RecommendationsConstants.setIsLoadingRecommendations,
274
274
  payload: { isLoadingRecommendations: false },
@@ -50,7 +50,7 @@ export function useAB(options = {}) {
50
50
  setTestVariation(ABEnum.B);
51
51
  }
52
52
  // eslint-disable-next-line react-hooks/exhaustive-deps
53
- }, [pcmConfig.data, loggedInUsersAccount.data.accountNumber, caseDispatch]);
53
+ }, [pcmConfig.data, loggedInUsersAccount.data.accountNumber, caseDispatch, caseType]);
54
54
  return {
55
55
  variation: testVariation,
56
56
  isVariationA: testVariation === ABEnum.A,
@@ -772,10 +772,11 @@ a.case-resource-recommendation-link {
772
772
  }
773
773
 
774
774
  .description-textarea {
775
- resize: none !important;
775
+ resize: vertical !important;
776
776
  &.pf-v6-c-form-control {
777
777
  &:disabled,
778
778
  &.kt1-disabled {
779
+ resize: none !important;
779
780
  &::after,
780
781
  &:after {
781
782
  border-block-end: none !important;
@@ -0,0 +1,3 @@
1
+ export declare const DEFAULT_ENGAGEMENT_WINDOW: number;
2
+ export declare const calculateEngagementWindow: (text: string, shouldCleanMarkdown?: boolean) => number;
3
+ //# sourceMappingURL=engagementUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engagementUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/engagementUtils.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,yBAAyB,QAAuC,CAAC;AAE9E,eAAO,MAAM,yBAAyB,SAAU,MAAM,wBAAuB,OAAO,KAAU,MAiB7F,CAAC"}
@@ -0,0 +1,16 @@
1
+ const MIN_ENGAGEMENT_WINDOW_SECONDS = 12;
2
+ const MAX_ENGAGEMENT_WINDOW_SECONDS = 90;
3
+ export const DEFAULT_ENGAGEMENT_WINDOW = MIN_ENGAGEMENT_WINDOW_SECONDS * 1000;
4
+ export const calculateEngagementWindow = (text, shouldCleanMarkdown = true) => {
5
+ const cleanedText = shouldCleanMarkdown
6
+ ? text
7
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
8
+ .replace(/`([^`]+)`/g, '$1')
9
+ .trim()
10
+ : text.trim();
11
+ const characterCount = cleanedText.length;
12
+ const wordCount = characterCount / 5;
13
+ const readingTimeSeconds = (wordCount / 220) * 60;
14
+ const engagementWindowSeconds = Math.min(Math.max(readingTimeSeconds * 1.5, MIN_ENGAGEMENT_WINDOW_SECONDS), MAX_ENGAGEMENT_WINDOW_SECONDS);
15
+ return engagementWindowSeconds * 1000;
16
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rh-support/troubleshoot",
3
- "version": "2.6.134",
3
+ "version": "2.6.136",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org"
@@ -133,5 +133,5 @@
133
133
  "defaults and supports es6-module",
134
134
  "maintained node versions"
135
135
  ],
136
- "gitHead": "568ccdf05848de9fc8ceae3544383d43345e9ee7"
136
+ "gitHead": "7d4dbe0e743fbcab5ee69035b77d12baab840c40"
137
137
  }
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- export default function TopContentSidebar(): React.JSX.Element;
3
- //# sourceMappingURL=TopContentSidebar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TopContentSidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/Suggestions/TopContentSidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAqB,MAAM,OAAO,CAAC;AAM1C,MAAM,CAAC,OAAO,UAAU,iBAAiB,sBA2CxC"}