@rh-support/troubleshoot 2.6.46 → 2.6.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/ActiveCustomerEscalation.d.ts +1 -0
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/ActiveCustomerEscalation.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/ActiveCustomerEscalation.js +31 -5
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.js +33 -34
- package/lib/esm/components/CaseEditView/CaseDetailsAside.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseDetailsAside.js +3 -2
- package/lib/esm/components/CaseEditView/CaseDetailsTabs.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseDetailsTabs.js +1 -0
- package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutions.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutions.js +14 -18
- package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutionsItem.js +1 -1
- package/lib/esm/components/CaseEditView/ConfirmationModals/ReopenCaseModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/ConfirmationModals/ReopenCaseModal.js +16 -22
- package/lib/esm/components/CaseEditView/RequestRemoteSession/ESSRemoteSession.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/ESSRemoteSession.js +2 -2
- package/lib/esm/components/CaseEditView/RequestRemoteSession/NewEssTermsModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/NewEssTermsModal.js +53 -102
- package/lib/esm/components/CaseEditView/RequestRemoteSession/RemoteSessionAgreement.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/RemoteSessionAgreement.js +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/RemoteSessionAgreementModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/RemoteSessionAgreementModal.js +23 -21
- package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseHostname.js +4 -2
- package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.js +7 -4
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.js +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/VerifyCaseStatusModal/VerifyCaseStatusModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/VerifyCaseStatusModal/VerifyCaseStatusModal.js +7 -9
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.css +0 -8
- package/lib/esm/components/CaseInformation/Fts.d.ts.map +1 -1
- package/lib/esm/components/CaseInformation/Fts.js +6 -2
- package/lib/esm/components/CaseInformation/Severity.js +1 -1
- package/lib/esm/components/CaseInformation/SupportLevel.d.ts.map +1 -1
- package/lib/esm/components/CaseInformation/SupportLevel.js +1 -1
- package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.d.ts +3 -0
- package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.d.ts.map +1 -1
- package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.js +15 -20
- package/lib/esm/components/CaseManagement/RHAssociatesSelector.d.ts.map +1 -1
- package/lib/esm/components/CaseManagement/RHAssociatesSelector.js +5 -7
- package/lib/esm/components/CaseManagement/SendNotifications/AddCustomEmailToAccountModal.d.ts.map +1 -1
- package/lib/esm/components/CaseManagement/SendNotifications/AddCustomEmailToAccountModal.js +20 -18
- package/lib/esm/components/CaseManagement/SendNotifications/CaseContactSelector.d.ts.map +1 -1
- package/lib/esm/components/CaseManagement/SendNotifications/CaseContactSelector.js +6 -9
- package/lib/esm/components/CaseManagement/SendNotifications/NonOrgCaseNotifyeesSelector.d.ts.map +1 -1
- package/lib/esm/components/CaseManagement/SendNotifications/NonOrgCaseNotifyeesSelector.js +22 -15
- package/lib/esm/components/Cve/CveModal.d.ts.map +1 -1
- package/lib/esm/components/Cve/CveModal.js +2 -3
- package/lib/esm/components/Cve/CveSidebar.js +1 -1
- package/lib/esm/components/OpenCase/SupportTypeSelectorPage.js +1 -1
- package/lib/esm/components/ProductSelector/AllProductsSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/AllProductsSelector.js +6 -9
- package/lib/esm/components/ProductSelector/NewProductDropdownSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/NewProductDropdownSelector.js +1 -10
- package/lib/esm/components/Recommendations/AsideResults.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/AsideResults.js +3 -3
- package/lib/esm/components/Recommendations/ClusterRecommendationsModal.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/ClusterRecommendationsModal.js +4 -7
- package/lib/esm/components/Recommendations/EARules/EARuleInfoAccordion.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/EARules/EARuleInfoAccordion.js +1 -3
- package/lib/esm/components/Recommendations/InsightsResults.js +1 -1
- package/lib/esm/components/Recommendations/InsightsRuleInfo.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/InsightsRuleInfo.js +2 -9
- package/lib/esm/components/Recommendations/RecommendationFeedbackModal.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/RecommendationFeedbackModal.js +4 -4
- package/lib/esm/components/Recommendations/Recommendations.js +2 -2
- package/lib/esm/components/Recommendations/RulesModal.d.ts.map +1 -1
- package/lib/esm/components/Recommendations/RulesModal.js +4 -7
- package/lib/esm/components/Recommendations/WatsonxAiIcon.js +1 -1
- package/lib/esm/components/SessionRestore/RestoreLastSessionModal.d.ts.map +1 -1
- package/lib/esm/components/SessionRestore/RestoreLastSessionModal.js +3 -5
- package/lib/esm/components/SessionRestore/SessionRestore.js +1 -1
- package/lib/esm/components/Suggestions/Suggestions.d.ts.map +1 -1
- package/lib/esm/components/Suggestions/Suggestions.js +12 -17
- package/lib/esm/components/Suggestions/TopContent.d.ts.map +1 -1
- package/lib/esm/components/Suggestions/TopContent.js +13 -13
- package/lib/esm/components/TroubleshootSection/AskRedHat.d.ts +7 -0
- package/lib/esm/components/TroubleshootSection/AskRedHat.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/AskRedHat.js +176 -0
- package/lib/esm/components/TroubleshootSection/CloseButton.d.ts +9 -0
- package/lib/esm/components/TroubleshootSection/CloseButton.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/CloseButton.js +5 -0
- package/lib/esm/components/TroubleshootSection/QuickResponse.d.ts +15 -0
- package/lib/esm/components/TroubleshootSection/QuickResponse.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/QuickResponse.js +26 -0
- package/lib/esm/components/TroubleshootSection/ResponseActionButton.d.ts +18 -0
- package/lib/esm/components/TroubleshootSection/ResponseActionButton.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/ResponseActionButton.js +28 -0
- package/lib/esm/components/TroubleshootSection/ResponseActions.d.ts +20 -0
- package/lib/esm/components/TroubleshootSection/ResponseActions.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/ResponseActions.js +52 -0
- package/lib/esm/components/TroubleshootSection/TroubleshootSection.d.ts +7 -0
- package/lib/esm/components/TroubleshootSection/TroubleshootSection.d.ts.map +1 -1
- package/lib/esm/components/TroubleshootSection/TroubleshootSection.js +99 -13
- package/lib/esm/components/TroubleshootSection/UserFeedback.d.ts +12 -0
- package/lib/esm/components/TroubleshootSection/UserFeedback.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/UserFeedback.js +44 -0
- package/lib/esm/components/TroubleshootSection/UserFeedbackComplete.d.ts +10 -0
- package/lib/esm/components/TroubleshootSection/UserFeedbackComplete.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/UserFeedbackComplete.js +46 -0
- package/lib/esm/components/TroubleshootSection/icons/CollapseIcon.d.ts +9 -0
- package/lib/esm/components/TroubleshootSection/icons/CollapseIcon.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/icons/CollapseIcon.js +9 -0
- package/lib/esm/components/TroubleshootSection/icons/StarIcon.d.ts +9 -0
- package/lib/esm/components/TroubleshootSection/icons/StarIcon.d.ts.map +1 -0
- package/lib/esm/components/TroubleshootSection/icons/StarIcon.js +17 -0
- package/lib/esm/components/shared/fileUpload/WidgetFileUploader.js +3 -3
- package/lib/esm/components/shared/fileUpload/css/fileSelector.css +0 -1
- package/lib/esm/components/shared/input/ContactSelectorInternal.d.ts +0 -1
- package/lib/esm/components/shared/input/ContactSelectorInternal.d.ts.map +1 -1
- package/lib/esm/components/shared/input/ContactSelectorInternal.js +1 -6
- package/lib/esm/components/shared/useIsSectionValid.d.ts.map +1 -1
- package/lib/esm/components/shared/useIsSectionValid.js +1 -7
- package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.js +2 -8
- package/lib/esm/components/wizardLayout/WizardAside.js +3 -3
- package/lib/esm/components/wizardLayout/WizardLayout.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/WizardLayout.js +9 -6
- package/lib/esm/components/wizardLayout/WizardMain.d.ts +7 -1
- package/lib/esm/components/wizardLayout/WizardMain.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/WizardMain.js +217 -18
- package/lib/esm/components/wizardLayout/WizardNavigation.d.ts +4 -2
- package/lib/esm/components/wizardLayout/WizardNavigation.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/WizardNavigation.js +13 -16
- package/lib/esm/components/wizardLayout/index.d.ts +1 -0
- package/lib/esm/components/wizardLayout/index.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/index.js +1 -0
- package/lib/esm/constants/askRedHatMessages.d.ts +35 -0
- package/lib/esm/constants/askRedHatMessages.d.ts.map +1 -0
- package/lib/esm/constants/askRedHatMessages.js +36 -0
- package/lib/esm/context/AIResponseContext.d.ts +10 -0
- package/lib/esm/context/AIResponseContext.d.ts.map +1 -0
- package/lib/esm/context/AIResponseContext.js +26 -0
- package/lib/esm/context/RootTroubleshootProvider.d.ts.map +1 -1
- package/lib/esm/context/RootTroubleshootProvider.js +8 -6
- package/lib/esm/css/AskRedHat.css +359 -0
- package/lib/esm/css/app.css +4 -5
- package/lib/esm/css/case.css +6 -39
- package/lib/esm/css/results.css +2 -2
- package/lib/esm/hooks/useWizard.d.ts +6 -0
- package/lib/esm/hooks/useWizard.d.ts.map +1 -1
- package/lib/esm/hooks/useWizard.js +1 -1
- package/lib/esm/reducers/AIResponseConstNTypes.d.ts +48 -0
- package/lib/esm/reducers/AIResponseConstNTypes.d.ts.map +1 -0
- package/lib/esm/reducers/AIResponseConstNTypes.js +18 -0
- package/lib/esm/reducers/AIResponseReducer.d.ts +9 -0
- package/lib/esm/reducers/AIResponseReducer.d.ts.map +1 -0
- package/lib/esm/reducers/AIResponseReducer.js +42 -0
- package/lib/esm/reducers/CaseConstNTypes.d.ts +2 -0
- package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
- package/lib/esm/reducers/CaseConstNTypes.js +2 -0
- package/lib/esm/scss/_main.scss +22 -84
- package/lib/esm/scss/_pf-overrides.scss +10 -37
- package/package.json +7 -6
|
@@ -39,14 +39,14 @@ function WizardAside(props) {
|
|
|
39
39
|
React.createElement("section", { className: "grid-aside-content" },
|
|
40
40
|
canUseSessionManagement && !isCreatingCase && activeSection !== AppRouteSections.SUBMIT_CASE && (React.createElement(SessionRestore, { routeProps: props.routeProps })),
|
|
41
41
|
canShowFileUploadWidget() && React.createElement(InsightsResults, null),
|
|
42
|
-
canShowFileUploadWidget() && React.createElement(FileDiag, { className: "pf-v6-u-mb-
|
|
42
|
+
canShowFileUploadWidget() && React.createElement(FileDiag, { className: "pf-v6-u-mb-md" }),
|
|
43
43
|
activeSection === (isCaseCreate ? AppRouteSections.SUMMARIZE : AppRouteSections.TROUBLESHOOT) &&
|
|
44
44
|
!isCveModalOpened && React.createElement(CveSidebar, null),
|
|
45
45
|
activeSection === AppRouteSections.RESOURCES && React.createElement(CveSidebar, null),
|
|
46
46
|
canShowEARuleWidget && React.createElement(EARuleWidget, null),
|
|
47
|
-
!(isIdea && activeSection === 'submit-case') && (React.createElement(AsideResults, { routeProps: props.routeProps, className: "pf-v6-u-mb-
|
|
47
|
+
!(isIdea && activeSection === 'submit-case') && (React.createElement(AsideResults, { routeProps: props.routeProps, className: "pf-v6-u-mb-md pf-v6-u-mt-0" })),
|
|
48
48
|
canShowFileRecommendationSectionsWidget && React.createElement(InsightsResults, { isDisplayOnMain: true }),
|
|
49
|
-
React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v6-u-mb-
|
|
49
|
+
React.createElement(ClusterRecommendations, { showClusterRecommendationsList: canShowClusterIdReportWidget, className: "pf-v6-u-mb-md pf-v6-u-mt-0" }))));
|
|
50
50
|
}
|
|
51
51
|
WizardAside.defaultProps = defaultProps;
|
|
52
52
|
export default WizardAside;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WizardLayout.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardLayout.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,EAAuC,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAcvG,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;CACpD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"WizardLayout.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardLayout.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,EAAuC,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAcvG,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;CACpD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,qBA+NzC"}
|
|
@@ -33,20 +33,23 @@ import { GlobalTroubleshootEffects } from './GlobalTroubleshootEffects';
|
|
|
33
33
|
import WizardAside from './WizardAside';
|
|
34
34
|
import WizardMain from './WizardMain';
|
|
35
35
|
export function WizardLayout(props) {
|
|
36
|
+
var _a, _b, _c, _d;
|
|
36
37
|
const { routeState: { activeSection, isCaseCreate }, } = useContext(RouteContext);
|
|
37
38
|
const { getMetadata } = useMetadata();
|
|
38
|
-
const
|
|
39
|
+
const [isAIChatMode, setIsAIChatMode] = useState(false);
|
|
40
|
+
const { caseCreationError, contactSSOName, caseType, product, caseState, ABTestVariation, hasInvalidEntitlements } = useCaseSelector((state) => ({
|
|
39
41
|
caseState: state,
|
|
40
42
|
caseCreationError: state.caseCreationError,
|
|
41
43
|
contactSSOName: state.caseDetails.contactSSOName,
|
|
42
44
|
caseType: state.caseDetails.caseType,
|
|
43
45
|
product: state.caseDetails.product,
|
|
44
46
|
ABTestVariation: state.ABTestVariation,
|
|
47
|
+
hasInvalidEntitlements: state.hasInvalidEntitlements,
|
|
45
48
|
}), isEqual);
|
|
46
49
|
const sessionRestoreDispatch = useContext(SessionRestoreDispatchContext);
|
|
47
50
|
const caseDispatch = useCaseDispatch();
|
|
48
51
|
const { sessionRestore: { activeSessionId, previousSessions }, } = useContext(SessionRestoreStateContext);
|
|
49
|
-
const { globalMetadataState: { allProducts, loggedInUser, loggedInUsersAccount, pcmConfig }, } = useContext(GlobalMetadataStateContext);
|
|
52
|
+
const { globalMetadataState: { allProducts, loggedInUser, loggedInUsersAccount, loggedInUserRights, pcmConfig }, } = useContext(GlobalMetadataStateContext);
|
|
50
53
|
const dispatchToGlobalMetadataReducer = useContext(GlobalMetadataDispatchContext);
|
|
51
54
|
const canAddAttachments = ability.can(resourceActions.PATCH, resources.CASE_CREATE, CaseListFields.ATTACHMENTS);
|
|
52
55
|
const { attachmentState } = useContext(AttachmentStateContext);
|
|
@@ -152,9 +155,9 @@ export function WizardLayout(props) {
|
|
|
152
155
|
React.createElement(GlobalTroubleshootEffects, { routeProps: props.routeProps }),
|
|
153
156
|
activeSection !== AppRouteSections.DESCRIBE_IDEA && (React.createElement(PreCaseConfirmationModals, { onModalClose: onModalClose, confirmationModalType: confirmationModalType, onConfirm: () => submitCaseAndNavigate(caseCreationError) })),
|
|
154
157
|
React.createElement(Grid, { style: { height: '100%' } },
|
|
155
|
-
React.createElement(GridItem, { sm: 12, md: 12, lg: 8, xl2: 8 },
|
|
156
|
-
React.createElement(WizardMain, { routeProps: props.routeProps, submitCaseAndNavigate: submitCaseAndNavigate, confirmSupportModal: confirmSupportModal })),
|
|
157
|
-
React.createElement(GridItem, { span: 4, className: "grid-wizard-aside-content" },
|
|
158
|
-
React.createElement(WizardAside, { isAttachmentUploadModalOpen: confirmationModalType === PreCaseConfirmationModalsEnum.NO_ATTACHMENT_MODAL, routeProps: props.routeProps }))),
|
|
158
|
+
React.createElement(GridItem, { sm: 12, md: 12, lg: isAIChatMode ? 12 : 8, xl2: isAIChatMode ? 12 : 8 },
|
|
159
|
+
React.createElement(WizardMain, { routeProps: props.routeProps, submitCaseAndNavigate: submitCaseAndNavigate, confirmSupportModal: confirmSupportModal, isAIChatMode: isAIChatMode, setIsAIChatMode: setIsAIChatMode, isSecureSupport: (_a = loggedInUsersAccount === null || loggedInUsersAccount === void 0 ? void 0 : loggedInUsersAccount.data) === null || _a === void 0 ? void 0 : _a.secureSupport, hasConfirmedStatesideSupport: (_b = loggedInUsersAccount === null || loggedInUsersAccount === void 0 ? void 0 : loggedInUsersAccount.data) === null || _b === void 0 ? void 0 : _b.hasConfirmedStatesideSupport, isUserExternal: (_d = (_c = loggedInUserRights === null || loggedInUserRights === void 0 ? void 0 : loggedInUserRights.data) === null || _c === void 0 ? void 0 : _c.isExternal()) !== null && _d !== void 0 ? _d : false, hasInvalidEntitlements: hasInvalidEntitlements })),
|
|
160
|
+
!isAIChatMode && (React.createElement(GridItem, { span: 4, className: "grid-wizard-aside-content" },
|
|
161
|
+
React.createElement(WizardAside, { isAttachmentUploadModalOpen: confirmationModalType === PreCaseConfirmationModalsEnum.NO_ATTACHMENT_MODAL, routeProps: props.routeProps })))),
|
|
159
162
|
React.createElement(AlertToastWrapper, { submitCaseAndNavigate: submitCaseAndNavigate, routeProps: props.routeProps })));
|
|
160
163
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { Dispatch, SetStateAction } from 'react';
|
|
2
2
|
import { RouteComponentProps } from 'react-router-dom';
|
|
3
3
|
import { IRouteUrlParams } from '../../reducers/RouteConstNTypes';
|
|
4
4
|
interface IProps {
|
|
5
5
|
routeProps: RouteComponentProps<IRouteUrlParams>;
|
|
6
6
|
submitCaseAndNavigate: (isReSubmitting: boolean) => void;
|
|
7
7
|
confirmSupportModal: (hasPreferredSecureSupportAccount: boolean) => void;
|
|
8
|
+
isAIChatMode: boolean;
|
|
9
|
+
setIsAIChatMode: Dispatch<SetStateAction<boolean>>;
|
|
10
|
+
isSecureSupport?: boolean;
|
|
11
|
+
hasConfirmedStatesideSupport?: boolean;
|
|
12
|
+
isUserExternal?: boolean;
|
|
13
|
+
hasInvalidEntitlements?: boolean;
|
|
8
14
|
}
|
|
9
15
|
declare function WizardMain(props: IProps): React.JSX.Element;
|
|
10
16
|
export default WizardMain;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WizardMain.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardMain.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WizardMain.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardMain.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAqD,MAAM,OAAO,CAAC;AAE3G,OAAO,EAAS,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAe9D,OAAO,EAAoB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AA0FpF,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,qBA6XhC;AACD,eAAe,UAAU,CAAC"}
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
1
10
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
11
|
var t = {};
|
|
3
12
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -9,16 +18,21 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
18
|
}
|
|
10
19
|
return t;
|
|
11
20
|
};
|
|
12
|
-
import {
|
|
21
|
+
import { Env } from '@cee-eng/hydrajs';
|
|
22
|
+
import { askRHDirectAIResponse, getRHDirectStatusCheck, } from '@ifd-ui/ask-redhat-core';
|
|
23
|
+
import { useWizardContext, Wizard, WizardNav, WizardNavItem, WizardStep } from '@patternfly/react-core';
|
|
13
24
|
import { LoadingIndicator } from '@rh-support/components';
|
|
14
25
|
import isEqual from 'lodash/isEqual';
|
|
15
26
|
import React, { Suspense, useContext, useEffect, useRef, useState } from 'react';
|
|
16
27
|
import { useTranslation } from 'react-i18next';
|
|
17
28
|
import { Route } from 'react-router-dom';
|
|
29
|
+
import { useAIResponseDispatch, useAIResponseState } from '../../context/AIResponseContext';
|
|
18
30
|
import { useCaseSelector } from '../../context/CaseContext';
|
|
19
31
|
import { RecommendationDispatchContext } from '../../context/RecommendationContext';
|
|
20
32
|
import { RouteContext, RouteDispatchContext } from '../../context/RouteContext';
|
|
21
33
|
import { useWizard } from '../../hooks/useWizard';
|
|
34
|
+
import { streamingChunkReceived, streamingCompleted, streamingError, streamingStarted, } from '../../reducers/AIResponseReducer';
|
|
35
|
+
import { appSourceId_ARH, excludedCaseTypesforARH } from '../../reducers/CaseConstNTypes';
|
|
22
36
|
import { RecommendationsConstants } from '../../reducers/RecommendationsReducer';
|
|
23
37
|
import { AppRouteSections } from '../../reducers/RouteConstNTypes';
|
|
24
38
|
import { setActiveSectionChanged, updateisNextBtnClickedToShowValidationError } from '../../reducers/RouteReducer';
|
|
@@ -27,22 +41,84 @@ import SubmitCase from '../SubmitCase/SubmitCase';
|
|
|
27
41
|
import MainSection from './MainSection';
|
|
28
42
|
import NewFeatureModal from './NewFeatureModal';
|
|
29
43
|
import WizardNavigation from './WizardNavigation';
|
|
44
|
+
// Mapping for case type display text in AI questions
|
|
45
|
+
const CASE_TYPE_AI_TEXT_MAP = {
|
|
46
|
+
Other: 'Something',
|
|
47
|
+
};
|
|
48
|
+
const getCaseTypeAIText = (caseType) => {
|
|
49
|
+
return CASE_TYPE_AI_TEXT_MAP[caseType] || caseType;
|
|
50
|
+
};
|
|
51
|
+
const generateCaseTypePrefix = (activeSection, caseType, lang) => {
|
|
52
|
+
if (activeSection === AppRouteSections.TROUBLESHOOT) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
const helpWith = getCaseTypeAIText(caseType);
|
|
56
|
+
const helpWithMap = {
|
|
57
|
+
en: `I want help with ${helpWith}.`,
|
|
58
|
+
de: `Ich benoetige Hilfe bei ${helpWith}.`,
|
|
59
|
+
zh: `我需要 ${helpWith} 方面的帮助。`,
|
|
60
|
+
pt: `Eu quero ajuda com ${helpWith}.`,
|
|
61
|
+
fr: `Je souhaite obtenir de l'aide pour ${helpWith}.`,
|
|
62
|
+
ko: `${helpWith}에 대한 도움이 필요합니다.`,
|
|
63
|
+
it: `Vorrei aiuto con un ${helpWith}.`,
|
|
64
|
+
ja: `${helpWith}のサポートを希望します。`,
|
|
65
|
+
ru: `Я хочу помощь с ${helpWith}.`,
|
|
66
|
+
es: `Quiero ayuda con ${helpWith}.`,
|
|
67
|
+
};
|
|
68
|
+
return helpWithMap[lang] || helpWithMap.en;
|
|
69
|
+
};
|
|
70
|
+
// Generate AI question based on case details
|
|
71
|
+
const generateAIQuestion = (activeSection, product, version, summary, issue, caseType, lang) => {
|
|
72
|
+
const baseMessageMap = {
|
|
73
|
+
en: `My issue is primarily related to ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}. I would title my problem: ${summary !== null && summary !== void 0 ? summary : ''}. More details are as follows: ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
74
|
+
de: `Mein Problem hängt hauptsächlich mit ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''} zusammen. Ich würde mein Problem so betiteln: ${summary !== null && summary !== void 0 ? summary : ''}. Weitere Details sind wie folgt: ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
75
|
+
zh: `我的问题主要与${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}有关。我会将我的问题命名为:${summary !== null && summary !== void 0 ? summary : ''}。更多细节如下:${issue !== null && issue !== void 0 ? issue : ''}。`,
|
|
76
|
+
pt: `Meu problema está principalmente relacionado a ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}. Eu daria ao meu problema o título: ${summary !== null && summary !== void 0 ? summary : ''}. Mais detalhes são os seguintes: ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
77
|
+
fr: `Mon problème est principalement lié à ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}. Je donnerais à mon problème le titre : ${summary !== null && summary !== void 0 ? summary : ''}. Plus de détails sont les suivants : ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
78
|
+
ko: `내 문제는 주로 ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}과(와) 관련이 있습니다. 내 문제의 제목은 ${summary !== null && summary !== void 0 ? summary : ''}입니다. 자세한 내용은 다음과 같습니다: ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
79
|
+
it: `Il mio problema è principalmente legato a ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}. Intitolerei il mio problema: ${summary !== null && summary !== void 0 ? summary : ''}. Ulteriori dettagli sono i seguenti: ${issue !== null && issue !== void 0 ? issue : ''}`,
|
|
80
|
+
ja: `私の問題は主に${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}に関係しています。問題のタイトルは: ${summary !== null && summary !== void 0 ? summary : ''}です。詳細は次のとおりです: ${issue !== null && issue !== void 0 ? issue : ''}。`,
|
|
81
|
+
ru: `Моя проблема в основном связана с ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}. Я бы назвал свою проблему: ${summary !== null && summary !== void 0 ? summary : ''}. Дополнительные подробности следующие: ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
82
|
+
es: `Mi problema está principalmente relacionado con ${product !== null && product !== void 0 ? product : ''} ${version !== null && version !== void 0 ? version : ''}. Titularía mi problema: ${summary !== null && summary !== void 0 ? summary : ''}. Más detalles son los siguientes: ${issue !== null && issue !== void 0 ? issue : ''}.`,
|
|
83
|
+
};
|
|
84
|
+
const prefix = generateCaseTypePrefix(activeSection, caseType, lang);
|
|
85
|
+
return `${prefix} ${baseMessageMap[lang] || baseMessageMap.en}`;
|
|
86
|
+
};
|
|
30
87
|
function WizardMain(props) {
|
|
31
88
|
const [showRestFlag, setShowRestFlag] = useState(false);
|
|
89
|
+
const [aiServicesAvailable, setAIServicesAvailable] = useState(false); // default to false until services are confirmed available
|
|
32
90
|
const recommendationDispatch = useContext(RecommendationDispatchContext);
|
|
33
|
-
const { isCreatingCase } = useCaseSelector((state) => ({
|
|
91
|
+
const { isCreatingCase, product, version, summary, issue, caseType, caseLanguage } = useCaseSelector((state) => ({
|
|
34
92
|
isCreatingCase: state.isCreatingCase,
|
|
93
|
+
product: state.caseDetails.product,
|
|
94
|
+
version: state.caseDetails.version,
|
|
95
|
+
summary: state.caseDetails.summary,
|
|
96
|
+
issue: state.caseDetails.issue,
|
|
97
|
+
caseType: state.caseDetails.caseType,
|
|
98
|
+
caseLanguage: state.caseDetails.caseLanguage,
|
|
35
99
|
}), isEqual);
|
|
36
|
-
const { routeState: { isCaseCreate }, } = useContext(RouteContext);
|
|
100
|
+
const { routeState: { isCaseCreate, activeSection }, } = useContext(RouteContext);
|
|
101
|
+
const aiResponseDispatch = useAIResponseDispatch();
|
|
102
|
+
const isTroubleshootSection = activeSection === AppRouteSections.TROUBLESHOOT;
|
|
103
|
+
const isResourcesSection = activeSection === AppRouteSections.RESOURCES;
|
|
104
|
+
const isSummarizeSection = activeSection === AppRouteSections.SUMMARIZE;
|
|
37
105
|
const [userSeenRecommendations, setUserSeenRecommendations] = useState(false);
|
|
38
106
|
const [userClickedNextonRecommendations, setUserClickedNextonRecommendations] = useState(false);
|
|
39
107
|
const [userScrolledLabel, setUserScrolledLabel] = useState(false);
|
|
40
108
|
const [userCanNavigateToTroubleshoot, setUserCanNavigateToTroubleshoot] = useState(false);
|
|
41
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
42
109
|
const [isNextButtonClicked, setIsNextButtonClicked] = useState(false);
|
|
43
110
|
const isNextButtonClickedRef = useRef(false);
|
|
44
111
|
const isBackButtonClickedRef = useRef(false);
|
|
45
112
|
const resultsRowRef = useRef(null);
|
|
113
|
+
const previousARHFieldsRef = useRef({
|
|
114
|
+
product: product,
|
|
115
|
+
version: version,
|
|
116
|
+
summary: summary,
|
|
117
|
+
issue: issue,
|
|
118
|
+
});
|
|
119
|
+
const handleChatWithAIClick = () => {
|
|
120
|
+
props.setIsAIChatMode(true);
|
|
121
|
+
};
|
|
46
122
|
const { getStepsSequece } = useWizard(props.routeProps, {
|
|
47
123
|
userSeenRecommendationsfn: setUserSeenRecommendations,
|
|
48
124
|
userSeenRecommendationsValue: userSeenRecommendations,
|
|
@@ -50,12 +126,91 @@ function WizardMain(props) {
|
|
|
50
126
|
userClickedNextonRecommendationsValue: userClickedNextonRecommendations,
|
|
51
127
|
resultsRowRef: resultsRowRef,
|
|
52
128
|
userScrolledLabel: userScrolledLabel,
|
|
129
|
+
isAIChatMode: props.isAIChatMode,
|
|
130
|
+
setIsAIChatMode: props.setIsAIChatMode,
|
|
131
|
+
onChatWithAIClick: handleChatWithAIClick,
|
|
132
|
+
aiServicesAvailable: aiServicesAvailable,
|
|
133
|
+
isSecureSupport: props.isSecureSupport,
|
|
134
|
+
hasConfirmedStatesideSupport: props.hasConfirmedStatesideSupport,
|
|
53
135
|
});
|
|
54
136
|
const dispatchToRouteReducer = useContext(RouteDispatchContext);
|
|
55
137
|
const { t } = useTranslation();
|
|
56
138
|
useEffect(() => {
|
|
57
139
|
setActiveSectionChanged(dispatchToRouteReducer, isCaseCreate ? AppRouteSections.GET_SUPPORT : AppRouteSections.TROUBLESHOOT, '');
|
|
58
140
|
}, [isCaseCreate, dispatchToRouteReducer]);
|
|
141
|
+
const shouldEnableARHServices = () => {
|
|
142
|
+
// Check if the current section is relevant for AI services
|
|
143
|
+
const isRelevantSection = isTroubleshootSection || isSummarizeSection || isResourcesSection;
|
|
144
|
+
// Check if the case type is allowed (not in the excluded list)
|
|
145
|
+
const isCaseTypeAllowed = !excludedCaseTypesforARH.includes(caseType || '');
|
|
146
|
+
// Check if user is not a secure support or confirmed stateside support user
|
|
147
|
+
const isNotSecureOrStatesideUser = !props.isSecureSupport && !props.hasConfirmedStatesideSupport;
|
|
148
|
+
// Check if the ARH fields have changed
|
|
149
|
+
const isARHFieldsChanged = haveARHFieldsChanged();
|
|
150
|
+
// Check if user is external and has invalid entitlements
|
|
151
|
+
const isNotUnentitledExternalUser = !(props.isUserExternal && props.hasInvalidEntitlements);
|
|
152
|
+
return (isRelevantSection &&
|
|
153
|
+
isCaseTypeAllowed &&
|
|
154
|
+
isNotSecureOrStatesideUser &&
|
|
155
|
+
isARHFieldsChanged &&
|
|
156
|
+
isNotUnentitledExternalUser);
|
|
157
|
+
};
|
|
158
|
+
// Check if any of the ARH-relevant fields have changed
|
|
159
|
+
const haveARHFieldsChanged = () => {
|
|
160
|
+
const hasChanged = previousARHFieldsRef.current.product !== product ||
|
|
161
|
+
previousARHFieldsRef.current.version !== version ||
|
|
162
|
+
previousARHFieldsRef.current.summary !== summary ||
|
|
163
|
+
previousARHFieldsRef.current.issue !== issue;
|
|
164
|
+
if (hasChanged) {
|
|
165
|
+
previousARHFieldsRef.current = {
|
|
166
|
+
product,
|
|
167
|
+
version,
|
|
168
|
+
summary,
|
|
169
|
+
issue,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return hasChanged;
|
|
173
|
+
};
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (!activeSection) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
//todo - need to revisit this logic
|
|
179
|
+
// if (!shouldEnableARHServices()) {
|
|
180
|
+
// if (aiServicesAvailable) {
|
|
181
|
+
// setAIServicesAvailable(false);
|
|
182
|
+
// }
|
|
183
|
+
// return;
|
|
184
|
+
// }
|
|
185
|
+
// check if ARH services are available
|
|
186
|
+
if (!aiServicesAvailable) {
|
|
187
|
+
const checkAIServices = () => __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
var _a, _b, _c;
|
|
189
|
+
const config = {
|
|
190
|
+
appSourceId: appSourceId_ARH,
|
|
191
|
+
authToken: (_b = (_a = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _a === void 0 ? void 0 : _a.getEncodedToken()) !== null && _b !== void 0 ? _b : '',
|
|
192
|
+
packageVersion: (_c = window === null || window === void 0 ? void 0 : window.supportVersionInfo) === null || _c === void 0 ? void 0 : _c.packageVersion,
|
|
193
|
+
appEnv: Env.getEnvName(),
|
|
194
|
+
};
|
|
195
|
+
try {
|
|
196
|
+
yield getRHDirectStatusCheck(config);
|
|
197
|
+
setAIServicesAvailable(true);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
setAIServicesAvailable(false);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
checkAIServices();
|
|
204
|
+
}
|
|
205
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
206
|
+
}, [
|
|
207
|
+
activeSection,
|
|
208
|
+
caseType,
|
|
209
|
+
isCaseCreate,
|
|
210
|
+
aiServicesAvailable,
|
|
211
|
+
props.isSecureSupport,
|
|
212
|
+
props.hasConfirmedStatesideSupport,
|
|
213
|
+
]);
|
|
59
214
|
const renderSubmitCasePage = () => (React.createElement(MainSection, { section: AppRouteSections.SUBMIT_CASE, title: t('Case has been submitted'), isLoading: isCreatingCase, description: t("We'll be in contact with you shortly. Look for updates on this case."), className: "case-submit-page" },
|
|
60
215
|
React.createElement(Suspense, { fallback: React.createElement(LoadingIndicator, { size: "sm" }) },
|
|
61
216
|
React.createElement(SubmitCase, { routeProps: props.routeProps }))));
|
|
@@ -100,26 +255,70 @@ function WizardMain(props) {
|
|
|
100
255
|
isBackButtonClickedRef.current = false;
|
|
101
256
|
setIsNextButtonClicked(false);
|
|
102
257
|
};
|
|
258
|
+
const handleReturnToCaseCreation = () => {
|
|
259
|
+
props.setIsAIChatMode(false);
|
|
260
|
+
};
|
|
103
261
|
const customNav = (isExpanded, steps, activeStep, goToStepByIndex) => (React.createElement(WizardNav, { isExpanded: isExpanded }, steps.map((step) => {
|
|
104
262
|
return (React.createElement(WizardNavItem, { key: step.id, id: step.id, content: step.name, isCurrent: activeStep.id === step.id, isDisabled: !step.canJumpTo, stepIndex: step.index, onClick: () => goToStepByIndex(step.index) }));
|
|
105
263
|
})));
|
|
106
|
-
const CustomFooter = (
|
|
264
|
+
const CustomFooter = () => {
|
|
265
|
+
var _a, _b, _c;
|
|
266
|
+
const { activeStep, goToNextStep, goToPrevStep, steps, goToStepByIndex } = useWizardContext(); // Correctly using the context
|
|
267
|
+
const aiResponseState = useAIResponseState();
|
|
268
|
+
const config = {
|
|
269
|
+
appSourceId: appSourceId_ARH,
|
|
270
|
+
authToken: (_b = (_a = window === null || window === void 0 ? void 0 : window.sessionjs) === null || _a === void 0 ? void 0 : _a.getEncodedToken()) !== null && _b !== void 0 ? _b : '',
|
|
271
|
+
packageVersion: (_c = window === null || window === void 0 ? void 0 : window.supportVersionInfo) === null || _c === void 0 ? void 0 : _c.packageVersion,
|
|
272
|
+
appEnv: Env.getEnvName(),
|
|
273
|
+
};
|
|
107
274
|
useEffect(() => {
|
|
108
|
-
if (steps.length > 2 &&
|
|
109
|
-
|
|
275
|
+
if (steps.length > 2 && activeStep.index === 2 && isNextButtonClicked) {
|
|
276
|
+
goToStepByIndex(3);
|
|
110
277
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
278
|
+
}, [activeStep, steps.length, goToStepByIndex]);
|
|
279
|
+
const fetchARHResponse = () => __awaiter(this, void 0, void 0, function* () {
|
|
280
|
+
var _a;
|
|
281
|
+
const detailedQuestion = generateAIQuestion(activeSection || '', product, version, summary, issue, caseType || '', caseLanguage || 'en');
|
|
282
|
+
//streaming callbacks
|
|
283
|
+
const streamingCallbacks = {
|
|
284
|
+
onChunk: (chunk, accumulatedResponse) => {
|
|
285
|
+
aiResponseDispatch(streamingChunkReceived(chunk, accumulatedResponse));
|
|
286
|
+
},
|
|
287
|
+
onComplete: (finalResponse) => {
|
|
288
|
+
aiResponseDispatch(streamingCompleted(finalResponse));
|
|
289
|
+
},
|
|
290
|
+
onError: (error) => {
|
|
291
|
+
aiResponseDispatch(streamingError(error));
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
aiResponseDispatch(streamingStarted());
|
|
295
|
+
try {
|
|
296
|
+
// Get existing conversation ID from state if available (need to map it with session data)
|
|
297
|
+
const existingConversationId = (_a = aiResponseState === null || aiResponseState === void 0 ? void 0 : aiResponseState.aiResponse) === null || _a === void 0 ? void 0 : _a.conversationId;
|
|
298
|
+
yield askRHDirectAIResponse(detailedQuestion, config, true, // response to be streamed or not
|
|
299
|
+
existingConversationId, streamingCallbacks);
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to get AI response';
|
|
303
|
+
aiResponseDispatch(streamingError(errorMessage));
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
const handleContinueClick = () => __awaiter(this, void 0, void 0, function* () {
|
|
307
|
+
// Navigate to next step first
|
|
308
|
+
isNextButtonClickedRef.current = true;
|
|
309
|
+
setIsNextButtonClicked(true);
|
|
310
|
+
goToNextStep();
|
|
311
|
+
focusWizardMainPanel();
|
|
312
|
+
// Fetch ARH response if conditions are met
|
|
313
|
+
if (shouldEnableARHServices() && aiServicesAvailable) {
|
|
314
|
+
yield fetchARHResponse();
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
return (React.createElement(WizardNavigation, { routeProps: props.routeProps, onNext: handleContinueClick, onBack: () => {
|
|
119
318
|
isBackButtonClickedRef.current = true;
|
|
120
|
-
goToPrevStep(
|
|
319
|
+
goToPrevStep();
|
|
121
320
|
focusWizardMainPanel();
|
|
122
|
-
}, activeStep: activeStep, onSubmit: onSubmit, confirmSupportModal: props.confirmSupportModal, onShowRestUpdate: (flag) => setShowRestFlag(flag), userSeenRecommendations: userSeenRecommendations, setUserSeenRecommendations: setUserSeenRecommendations, userClickedNextonRecommendationsFn: setUserClickedNextonRecommendations, userClickedNextonRecommendationsValue: userClickedNextonRecommendations, setUserCanNavigateToTroubleshoot: setUserCanNavigateToTroubleshoot, resultsRowRef: resultsRowRef, setUserScrolledLabel: setUserScrolledLabel }));
|
|
321
|
+
}, activeStep: activeStep, onSubmit: onSubmit, confirmSupportModal: props.confirmSupportModal, onShowRestUpdate: (flag) => setShowRestFlag(flag), userSeenRecommendations: userSeenRecommendations, setUserSeenRecommendations: setUserSeenRecommendations, userClickedNextonRecommendationsFn: setUserClickedNextonRecommendations, userClickedNextonRecommendationsValue: userClickedNextonRecommendations, setUserCanNavigateToTroubleshoot: setUserCanNavigateToTroubleshoot, resultsRowRef: resultsRowRef, setUserScrolledLabel: setUserScrolledLabel, isAIChatMode: props.isAIChatMode, onReturnToCaseCreation: handleReturnToCaseCreation }));
|
|
123
322
|
};
|
|
124
323
|
const steps = getStepsSequece(showRestFlag);
|
|
125
324
|
const wizardSteps = steps.map((step) => {
|
|
@@ -130,7 +329,7 @@ function WizardMain(props) {
|
|
|
130
329
|
// in useWizard file then add it to step squences in RouteConstNTypes
|
|
131
330
|
return (React.createElement(React.Fragment, null,
|
|
132
331
|
React.createElement(NewFeatureModal, null),
|
|
133
|
-
steps.length !== 0 && (React.createElement(Route, { path: `${RouteUtils.seBasePath}/(${steps[0].id}|describe-issue|open-case)`, render: () => (React.createElement(Wizard, { isVisitRequired: true, nav: customNav, navAriaLabel: ` navAriaLabel steps `, footer: CustomFooter, onStepChange: onCurrentStepChanged }, wizardSteps)) })),
|
|
332
|
+
steps.length !== 0 && (React.createElement(Route, { path: `${RouteUtils.seBasePath}/(${steps[0].id}|describe-issue|open-case)`, render: () => (React.createElement(Wizard, { isVisitRequired: true, nav: customNav, navAriaLabel: ` navAriaLabel steps `, footer: React.createElement(CustomFooter, null), onStepChange: onCurrentStepChanged }, wizardSteps)) })),
|
|
134
333
|
React.createElement(Route, { exact: true, path: `${RouteUtils.seBasePath}/${AppRouteSections.SUBMIT_CASE}`, render: () => renderSubmitCasePage() })));
|
|
135
334
|
}
|
|
136
335
|
export default WizardMain;
|
|
@@ -3,8 +3,8 @@ import { RouteComponentProps } from 'react-router-dom';
|
|
|
3
3
|
import { IRouteUrlParams, ISectionConfiguration } from '../../reducers/RouteConstNTypes';
|
|
4
4
|
interface IProps {
|
|
5
5
|
routeProps: RouteComponentProps<IRouteUrlParams>;
|
|
6
|
-
onNext: (
|
|
7
|
-
onBack: (
|
|
6
|
+
onNext: () => void;
|
|
7
|
+
onBack: () => void;
|
|
8
8
|
activeStep: Partial<ISectionConfiguration>;
|
|
9
9
|
onSubmit: () => void;
|
|
10
10
|
confirmSupportModal: (hasPreferredSecureSupportAccount: boolean) => void;
|
|
@@ -16,6 +16,8 @@ interface IProps {
|
|
|
16
16
|
setUserCanNavigateToTroubleshoot: (value: React.SetStateAction<boolean>) => void;
|
|
17
17
|
resultsRowRef?: any;
|
|
18
18
|
setUserScrolledLabel: (value: React.SetStateAction<boolean>) => void;
|
|
19
|
+
isAIChatMode?: boolean;
|
|
20
|
+
onReturnToCaseCreation?: () => void;
|
|
19
21
|
}
|
|
20
22
|
declare function WizardNavigation(props: IProps): React.JSX.Element;
|
|
21
23
|
declare namespace WizardNavigation {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WizardNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardNavigation.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAAoB,eAAe,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAM3G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"WizardNavigation.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/WizardNavigation.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAAoB,eAAe,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAM3G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,mBAAmB,EAAE,CAAC,gCAAgC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzE,gBAAgB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,0BAA0B,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5E,kCAAkC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACpF,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,gCAAgC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACjF,aAAa,CAAC,EAAE,GAAG,CAAC;IACpB,oBAAoB,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IACrE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AAGD,iBAAS,gBAAgB,CAAC,KAAK,EAAE,MAAM,qBAiVtC;kBAjVQ,gBAAgB;;;AAmVzB,eAAe,gBAAgB,CAAC"}
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { pcm } from '@cee-eng/hydrajs';
|
|
11
11
|
import { Button, ButtonVariant, WizardFooterWrapper } from '@patternfly/react-core';
|
|
12
|
-
import { useFetch
|
|
12
|
+
import { useFetch } from '@rh-support/components';
|
|
13
13
|
import { GlobalMetadataStateContext, useCanCreateCase } from '@rh-support/react-context';
|
|
14
14
|
import { dtmTrackEventCaseCreationStepEncountered, getResTypeFromUrl, PreviousToNewCaseTypeMap, scrollIntoView, } from '@rh-support/utils';
|
|
15
15
|
import find from 'lodash/find';
|
|
@@ -51,7 +51,6 @@ function WizardNavigation(props) {
|
|
|
51
51
|
const { activeSectionError, isSectionValidFn } = useIsSectionValid(activeSection);
|
|
52
52
|
const [isRecsModalVisible, setIsRecsModalVisible] = useState(false);
|
|
53
53
|
const previousRecommendationTop = useRef(0);
|
|
54
|
-
const previousStep = usePrevious(props.activeStep);
|
|
55
54
|
const { request: resolveSessionRequest } = useFetch(pcm.preCase.session.resolveSession);
|
|
56
55
|
const { sessionRestore: { activeSessionId, sessionResourceTracking }, } = useContext(SessionRestoreStateContext);
|
|
57
56
|
const { SessionResourceSource } = pcm.preCase.session;
|
|
@@ -60,15 +59,12 @@ function WizardNavigation(props) {
|
|
|
60
59
|
}), isEqual);
|
|
61
60
|
const caseDispatch = useCaseDispatch();
|
|
62
61
|
useEffect(() => {
|
|
63
|
-
var _a
|
|
64
|
-
if ((previousStep === null || previousStep === void 0 ? void 0 : previousStep.id) === ((_a = props.activeStep) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
62
|
+
var _a;
|
|
67
63
|
const isCreatingCase = RouteUtils.getQueryParams(props.routeProps).caseCreate === 'true';
|
|
68
64
|
dtmTrackEventCaseCreationStepEncountered(isCreatingCase,
|
|
69
65
|
// @ts-ignore
|
|
70
66
|
props.activeStep.name, props.activeStep.id === AppRouteSections.GET_SUPPORT ||
|
|
71
|
-
props.activeStep.id === AppRouteSections.TROUBLESHOOT, (
|
|
67
|
+
props.activeStep.id === AppRouteSections.TROUBLESHOOT, (_a = caseState.caseDetails) === null || _a === void 0 ? void 0 : _a.caseNumber, PreviousToNewCaseTypeMap[caseState.caseDetails.caseType], caseState.caseDetails.summary, caseState.caseDetails.product, caseState.caseDetails.version);
|
|
72
68
|
if (props.activeStep.id === AppRouteSections.RESOURCES) {
|
|
73
69
|
window.scrollTo({
|
|
74
70
|
top: 0,
|
|
@@ -76,7 +72,7 @@ function WizardNavigation(props) {
|
|
|
76
72
|
});
|
|
77
73
|
}
|
|
78
74
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
|
-
}, [
|
|
75
|
+
}, [props.activeStep.id]);
|
|
80
76
|
const [hasUserScrolled, setHasUserScrolled] = useState(false);
|
|
81
77
|
useEffect(() => {
|
|
82
78
|
if (props.activeStep.id !== (isCaseCreate ? AppRouteSections.SUMMARIZE : AppRouteSections.TROUBLESHOOT) ||
|
|
@@ -139,7 +135,7 @@ function WizardNavigation(props) {
|
|
|
139
135
|
}
|
|
140
136
|
};
|
|
141
137
|
}, [recommendationState.numFound, hasUserScrolled, props, isCaseCreate]);
|
|
142
|
-
const onNext = (
|
|
138
|
+
const onNext = () => {
|
|
143
139
|
var _a;
|
|
144
140
|
updateisNextBtnClickedToShowValidationError(dispatchToRouteReducer, true);
|
|
145
141
|
//handle the new changes for 13406:
|
|
@@ -175,19 +171,19 @@ function WizardNavigation(props) {
|
|
|
175
171
|
// to show all steps, a delay needed in order to steps array
|
|
176
172
|
// to be updated
|
|
177
173
|
window.setTimeout(() => {
|
|
178
|
-
props.onNext && props.onNext(
|
|
174
|
+
props.onNext && props.onNext();
|
|
179
175
|
}, 10);
|
|
180
176
|
}
|
|
181
177
|
else {
|
|
182
|
-
props.onNext && props.onNext(
|
|
178
|
+
props.onNext && props.onNext();
|
|
183
179
|
}
|
|
184
180
|
}
|
|
185
181
|
return;
|
|
186
182
|
};
|
|
187
|
-
const onBack = (
|
|
183
|
+
const onBack = () => {
|
|
188
184
|
if (props.activeStep.hidRestOnBack)
|
|
189
185
|
props.onShowRestUpdate(false);
|
|
190
|
-
props.onBack(
|
|
186
|
+
props.onBack();
|
|
191
187
|
};
|
|
192
188
|
const onRecsFeedbackModalToggle = () => {
|
|
193
189
|
setIsRecsModalVisible((visible) => !visible);
|
|
@@ -253,9 +249,10 @@ function WizardNavigation(props) {
|
|
|
253
249
|
// To handle entitled products
|
|
254
250
|
return (React.createElement(React.Fragment, null,
|
|
255
251
|
React.createElement(WizardFooterWrapper, null,
|
|
256
|
-
props.
|
|
257
|
-
|
|
258
|
-
|
|
252
|
+
props.isAIChatMode && activeSection === AppRouteSections.RESOURCES ? (React.createElement(Button, { onClick: props.onReturnToCaseCreation, variant: "link", className: "return-to-case-btn" }, isCaseCreate ? t('Return to case creation') : t('Return to resources'))) : (React.createElement(React.Fragment, null,
|
|
253
|
+
props.activeStep.order !== 0 && (React.createElement("button", { onClick: () => onBack(), className: "btn btn-app btn-open-white main-nav-button", "data-tracking-id": `prev-of-${activeSection}`, type: "button", disabled: isDisabledGoBack() }, t('Go back'))),
|
|
254
|
+
React.createElement("button", { disabled: nextButtonDisabledLogic(), onClick: onNext, className: "btn btn-app btn-primary main-nav-button", "data-tracking-id": `next-of-${activeSection}`, type: "button" }, t(props.activeStep.nextButtonLabel)),
|
|
255
|
+
activeSection === AppRouteSections.RESOURCES && isFileRecommendationsTriggered && (React.createElement(Button, { onClick: handleFileRecsSelfSolved, variant: ButtonVariant.secondary, className: "issue-solved-button solved-issue-button", "data-tracking-id": "troubleshoot-self-solved-issue" }, t('I solved my issue'))))),
|
|
259
256
|
React.createElement(RecommendationFeedbackModal, { isModalOpen: isRecsModalVisible, handleModalToggle: onRecsFeedbackModalToggle, modalContent: t(`Great, we're glad that resolved your issue`) }),
|
|
260
257
|
activeSectionError ? (React.createElement("small", { className: "pf-v6-u-align-self-center pf-v6-u-ml-md text-red" }, activeSectionError)) : null)));
|
|
261
258
|
}
|
|
@@ -2,6 +2,7 @@ import 'react-bootstrap-typeahead/css/Typeahead.css';
|
|
|
2
2
|
import '../../css/app.css';
|
|
3
3
|
import '../../css/pagination.css';
|
|
4
4
|
import '../../css/productSelector.css';
|
|
5
|
+
import '../../css/AskRedHat.css';
|
|
5
6
|
import '../../css/results.css';
|
|
6
7
|
import '../shared/fileUpload/css/fileSelector.css';
|
|
7
8
|
import React from 'react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/index.tsx"],"names":[],"mappings":"AAAA,OAAO,6CAA6C,CAAC;AACrD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,0BAA0B,CAAC;AAClC,OAAO,+BAA+B,CAAC;AACvC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,2CAA2C,CAAC;AAGnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,SAAS,EAAE,GAAG,CAAC;QACf,oBAAoB,EAAE,GAAG,CAAC;QAC1B,MAAM,EAAE,GAAG,CAAC;QACZ,KAAK,EAAE,GAAG,CAAC;QACX,aAAa,EAAE;YACX,cAAc,EAAE,MAAM,CAAC;YACvB,OAAO,EAAE,MAAM,CAAC;SACnB,CAAC;KACL;IAED,UAAU,QAAQ;QACd,YAAY,EAAE,GAAG,CAAC;KACrB;CACJ;AAED,eAAO,MAAM,YAAY,UAAW,MAAM,sBAYzC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/wizardLayout/index.tsx"],"names":[],"mappings":"AAAA,OAAO,6CAA6C,CAAC;AACrD,OAAO,mBAAmB,CAAC;AAC3B,OAAO,0BAA0B,CAAC;AAClC,OAAO,+BAA+B,CAAC;AACvC,OAAO,yBAAyB,CAAC;AACjC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,2CAA2C,CAAC;AAGnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAIvD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,MAAM;QACZ,SAAS,EAAE,GAAG,CAAC;QACf,oBAAoB,EAAE,GAAG,CAAC;QAC1B,MAAM,EAAE,GAAG,CAAC;QACZ,KAAK,EAAE,GAAG,CAAC;QACX,aAAa,EAAE;YACX,cAAc,EAAE,MAAM,CAAC;YACvB,OAAO,EAAE,MAAM,CAAC;SACnB,CAAC;KACL;IAED,UAAU,QAAQ;QACd,YAAY,EAAE,GAAG,CAAC;KACrB;CACJ;AAED,eAAO,MAAM,YAAY,UAAW,MAAM,sBAYzC,CAAC"}
|
|
@@ -2,6 +2,7 @@ import 'react-bootstrap-typeahead/css/Typeahead.css';
|
|
|
2
2
|
import '../../css/app.css';
|
|
3
3
|
import '../../css/pagination.css';
|
|
4
4
|
import '../../css/productSelector.css';
|
|
5
|
+
import '../../css/AskRedHat.css';
|
|
5
6
|
import '../../css/results.css';
|
|
6
7
|
import '../shared/fileUpload/css/fileSelector.css';
|
|
7
8
|
import { useDocumentTitle } from '@rh-support/components';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare const QUICK_RESPONSES: {
|
|
2
|
+
positive: {
|
|
3
|
+
id: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}[];
|
|
6
|
+
negative: {
|
|
7
|
+
id: string;
|
|
8
|
+
content: string;
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
export declare const TOOLTIP_MESSAGES: {
|
|
12
|
+
readonly positive: {
|
|
13
|
+
readonly tooltipContent: "Good response";
|
|
14
|
+
readonly clickedTooltipContent: "Response recorded as helpful";
|
|
15
|
+
};
|
|
16
|
+
readonly negative: {
|
|
17
|
+
readonly tooltipContent: "Bad response";
|
|
18
|
+
readonly clickedTooltipContent: "Response recorded as unhelpful";
|
|
19
|
+
};
|
|
20
|
+
readonly copy: {
|
|
21
|
+
readonly tooltipContent: "Copy";
|
|
22
|
+
readonly clickedTooltipContent: "Response copied";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare const MODAL_MESSAGES: {
|
|
26
|
+
readonly feedback: {
|
|
27
|
+
readonly positive: "Thank you. Any more feedback?";
|
|
28
|
+
readonly negative: "Thank you. How can we improve?";
|
|
29
|
+
};
|
|
30
|
+
readonly complete: {
|
|
31
|
+
readonly title: "We appreciate your input.";
|
|
32
|
+
readonly body: "It helps us improve this experience.";
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=askRedHatMessages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"askRedHatMessages.d.ts","sourceRoot":"","sources":["../../../src/constants/askRedHatMessages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe;;;;;;;;;CAW3B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;CAanB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;CASjB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const QUICK_RESPONSES = {
|
|
2
|
+
positive: [
|
|
3
|
+
{ id: '1', content: 'Solved my issue' },
|
|
4
|
+
{ id: '2', content: 'Easy to understand' },
|
|
5
|
+
{ id: '3', content: 'Accurate' },
|
|
6
|
+
],
|
|
7
|
+
negative: [
|
|
8
|
+
{ id: '1', content: "Didn't solve my issue" },
|
|
9
|
+
{ id: '2', content: 'Confusing' },
|
|
10
|
+
{ id: '3', content: 'Inaccurate' },
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
export const TOOLTIP_MESSAGES = {
|
|
14
|
+
positive: {
|
|
15
|
+
tooltipContent: 'Good response',
|
|
16
|
+
clickedTooltipContent: 'Response recorded as helpful',
|
|
17
|
+
},
|
|
18
|
+
negative: {
|
|
19
|
+
tooltipContent: 'Bad response',
|
|
20
|
+
clickedTooltipContent: 'Response recorded as unhelpful',
|
|
21
|
+
},
|
|
22
|
+
copy: {
|
|
23
|
+
tooltipContent: 'Copy',
|
|
24
|
+
clickedTooltipContent: 'Response copied',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export const MODAL_MESSAGES = {
|
|
28
|
+
feedback: {
|
|
29
|
+
positive: 'Thank you. Any more feedback?',
|
|
30
|
+
negative: 'Thank you. How can we improve?',
|
|
31
|
+
},
|
|
32
|
+
complete: {
|
|
33
|
+
title: 'We appreciate your input.',
|
|
34
|
+
body: 'It helps us improve this experience.',
|
|
35
|
+
},
|
|
36
|
+
};
|