@rh-support/troubleshoot 1.0.371-beta.2 → 1.0.371-beta.7

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 (106) hide show
  1. package/lib/esm/components/AccountInfo/OwnerSelector.d.ts.map +1 -1
  2. package/lib/esm/components/AccountInfo/OwnerSelector.js +63 -8
  3. package/lib/esm/components/CaseEditView/Case.d.ts.map +1 -1
  4. package/lib/esm/components/CaseEditView/Case.js +5 -4
  5. package/lib/esm/components/CaseEditView/CaseDetailsAside.js +1 -1
  6. package/lib/esm/components/CaseEditView/CaseDetailsTabs.d.ts +2 -0
  7. package/lib/esm/components/CaseEditView/CaseDetailsTabs.d.ts.map +1 -1
  8. package/lib/esm/components/CaseEditView/CaseDetailsTabs.js +2 -2
  9. package/lib/esm/components/CaseEditView/CaseDetailsWarningMessage.js +1 -1
  10. package/lib/esm/components/CaseEditView/CaseOverview/index.d.ts +2 -0
  11. package/lib/esm/components/CaseEditView/CaseOverview/index.d.ts.map +1 -1
  12. package/lib/esm/components/CaseEditView/CaseOverview/index.js +2 -0
  13. package/lib/esm/components/CaseEditView/CaseSecureSupportAlert.d.ts.map +1 -1
  14. package/lib/esm/components/CaseEditView/CaseSecureSupportAlert.js +1 -1
  15. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseAlternateId.d.ts.map +1 -1
  16. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseAlternateId.js +39 -21
  17. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.d.ts +2 -0
  18. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.d.ts.map +1 -0
  19. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.js +95 -0
  20. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseDetailsManagement.d.ts +2 -0
  21. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseDetailsManagement.d.ts.map +1 -1
  22. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseDetailsManagement.js +9 -1
  23. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseHostname.d.ts.map +1 -1
  24. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseHostname.js +1 -4
  25. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.d.ts.map +1 -1
  26. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.js +3 -1
  27. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.d.ts +9 -0
  28. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.d.ts.map +1 -0
  29. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.js +62 -0
  30. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/Summary.d.ts +1 -0
  31. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/Summary.d.ts.map +1 -1
  32. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/Summary.js +64 -27
  33. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseAttachment.d.ts.map +1 -1
  34. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseAttachment.js +16 -6
  35. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.js +1 -1
  36. package/lib/esm/components/CaseInformation/CaseGroup.d.ts.map +1 -1
  37. package/lib/esm/components/CaseInformation/CaseGroup.js +1 -32
  38. package/lib/esm/components/CaseInformation/ContactPhoneNumber.d.ts +2 -0
  39. package/lib/esm/components/CaseInformation/ContactPhoneNumber.d.ts.map +1 -0
  40. package/lib/esm/components/CaseInformation/ContactPhoneNumber.js +45 -0
  41. package/lib/esm/components/CaseInformation/ContactPhoneNumberAlert.d.ts +2 -0
  42. package/lib/esm/components/CaseInformation/ContactPhoneNumberAlert.d.ts.map +1 -0
  43. package/lib/esm/components/CaseInformation/ContactPhoneNumberAlert.js +33 -0
  44. package/lib/esm/components/CaseInformation/ContactPhoneNumberPopOver.d.ts +2 -0
  45. package/lib/esm/components/CaseInformation/ContactPhoneNumberPopOver.d.ts.map +1 -0
  46. package/lib/esm/components/CaseInformation/ContactPhoneNumberPopOver.js +12 -0
  47. package/lib/esm/components/CaseInformation/FileDiag.d.ts.map +1 -1
  48. package/lib/esm/components/CaseInformation/FileDiag.js +1 -1
  49. package/lib/esm/components/CaseInformation/Fts.d.ts.map +1 -1
  50. package/lib/esm/components/CaseInformation/Fts.js +2 -2
  51. package/lib/esm/components/CaseManagement/CaseManagement.d.ts.map +1 -1
  52. package/lib/esm/components/CaseManagement/CaseManagement.js +11 -3
  53. package/lib/esm/components/CaseManagement/OpenAlternateID.d.ts +10 -0
  54. package/lib/esm/components/CaseManagement/OpenAlternateID.d.ts.map +1 -0
  55. package/lib/esm/components/CaseManagement/OpenAlternateID.js +44 -0
  56. package/lib/esm/components/Issue/Issue.js +1 -1
  57. package/lib/esm/components/Recommendations/AsideResults.d.ts.map +1 -1
  58. package/lib/esm/components/Recommendations/InsightsResults.js +1 -1
  59. package/lib/esm/components/Recommendations/Recommendations.d.ts.map +1 -1
  60. package/lib/esm/components/Recommendations/Recommendations.js +1 -0
  61. package/lib/esm/components/Review/Review.d.ts.map +1 -1
  62. package/lib/esm/components/Review/Review.js +11 -3
  63. package/lib/esm/components/SessionRestore/RestoreLastSessionModal.d.ts.map +1 -1
  64. package/lib/esm/components/SessionRestore/RestoreLastSessionModal.js +6 -1
  65. package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.d.ts.map +1 -1
  66. package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.js +1 -1
  67. package/lib/esm/components/shared/fileUpload/FileLister.d.ts +1 -1
  68. package/lib/esm/components/shared/fileUpload/FileLister.d.ts.map +1 -1
  69. package/lib/esm/components/shared/fileUpload/FileLister.js +5 -2
  70. package/lib/esm/components/shared/fileUpload/FileUploader.js +1 -1
  71. package/lib/esm/components/shared/fileUpload/WidgetFileUploader.d.ts +2 -0
  72. package/lib/esm/components/shared/fileUpload/WidgetFileUploader.d.ts.map +1 -1
  73. package/lib/esm/components/shared/fileUpload/WidgetFileUploader.js +68 -2
  74. package/lib/esm/components/shared/fileUpload/css/fileSelector.css +1 -27
  75. package/lib/esm/components/shared/fileUpload/fileSelectors/WidgetFileSelector.js +1 -1
  76. package/lib/esm/components/shared/fileUpload/index.d.ts +1 -1
  77. package/lib/esm/components/shared/fileUpload/index.js +1 -1
  78. package/lib/esm/components/shared/fileUpload/reducer/AttachmentHelper.d.ts +1 -1
  79. package/lib/esm/components/shared/fileUpload/reducer/AttachmentHelper.d.ts.map +1 -1
  80. package/lib/esm/components/shared/fileUpload/reducer/AttachmentHelper.js +1 -1
  81. package/lib/esm/components/shared/fileUpload/reducer/{AttachemntReducer.d.ts → AttachmentReducer.d.ts} +1 -1
  82. package/lib/esm/components/shared/fileUpload/reducer/{AttachemntReducer.d.ts.map → AttachmentReducer.d.ts.map} +1 -1
  83. package/lib/esm/components/shared/fileUpload/reducer/AttachmentReducerContext.d.ts +1 -1
  84. package/lib/esm/components/shared/fileUpload/reducer/AttachmentReducerContext.js +1 -1
  85. package/lib/esm/components/shared/fileUpload/reducer/FileStatusHelper.d.ts +1 -1
  86. package/lib/esm/components/shared/fileUpload/reducer/FileStatusHelper.js +1 -1
  87. package/lib/esm/components/shared/fileUpload/useFileUploader.d.ts +1 -1
  88. package/lib/esm/components/shared/fileUpload/useFileUploader.d.ts.map +1 -1
  89. package/lib/esm/components/shared/fileUpload/useFileUploader.js +2 -4
  90. package/lib/esm/components/shared/useIsSectionValid.d.ts.map +1 -1
  91. package/lib/esm/components/shared/useIsSectionValid.js +6 -3
  92. package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.d.ts.map +1 -1
  93. package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.js +8 -0
  94. package/lib/esm/constants/caseDetailsConstants.d.ts +1 -0
  95. package/lib/esm/constants/caseDetailsConstants.d.ts.map +1 -1
  96. package/lib/esm/constants/caseDetailsConstants.js +1 -0
  97. package/lib/esm/css/app.css +5 -0
  98. package/lib/esm/reducers/CaseConstNTypes.d.ts +4 -0
  99. package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
  100. package/lib/esm/reducers/CaseConstNTypes.js +6 -0
  101. package/lib/esm/reducers/CaseHelpers.d.ts.map +1 -1
  102. package/lib/esm/reducers/CaseHelpers.js +16 -4
  103. package/lib/esm/reducers/CaseReducer.d.ts.map +1 -1
  104. package/lib/esm/reducers/CaseReducer.js +2 -0
  105. package/package.json +13 -10
  106. /package/lib/esm/components/shared/fileUpload/reducer/{AttachemntReducer.js → AttachmentReducer.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"OwnerSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/AccountInfo/OwnerSelector.tsx"],"names":[],"mappings":"AA4BA,UAAU,MAAM;CAAG;AAEnB,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,eA2NnC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"OwnerSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/AccountInfo/OwnerSelector.tsx"],"names":[],"mappings":"AAoCA,UAAU,MAAM;CAAG;AAEnB,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,eAuRnC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -7,6 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { contacts } from '@cee-eng/hydrajs';
10
11
  import { CaseContactsSelectorExternal, getHydraContactLabel, renderMenuItemChildren, ToastNotification, usePrevious, ValueChangedIcon, } from '@rh-support/components';
11
12
  import { GlobalMetadataStateContext, useCanEditCase } from '@rh-support/react-context';
12
13
  import { sortHydraContacts } from '@rh-support/utils';
@@ -20,24 +21,24 @@ import { Trans, useTranslation } from 'react-i18next';
20
21
  import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
21
22
  import { RouteContext } from '../../context/RouteContext';
22
23
  import { useCaseUpdateErrorMessage } from '../../hooks/useCaseUpdateErrorMessage';
23
- import { setCaseOwner, setNotifiedUser, updateCaseDetails } from '../../reducers/CaseReducer';
24
+ import { setCaseDetails, setCaseOwner, setCaseState, setNotifiedUser, updateCaseDetails, } from '../../reducers/CaseReducer';
24
25
  import { CaseValuesToWatch } from '../shared/Constants';
25
26
  import { getChangedValueTooltip } from '../shared/utils';
26
27
  function OwnerSelector(props) {
27
28
  const { t } = useTranslation();
28
29
  const caseUpdateError = useCaseUpdateErrorMessage();
29
- const { accountNumber, caseNumber, selectedNotificationContacts, selectedOwner, selectedCaseGroupUsers } = useCaseSelector((state) => ({
30
+ const { accountNumber, caseNumber, selectedNotificationContacts, selectedOwner, selectedCaseGroupUsers, isCaseOwnerUpdating, } = useCaseSelector((state) => ({
30
31
  accountNumber: state.caseDetails.accountNumberRef,
31
32
  caseNumber: state.caseDetails.caseNumber,
32
33
  selectedNotificationContacts: state.selectedNotificationContacts,
33
34
  selectedOwner: state.selectedOwner,
34
35
  selectedCaseGroupUsers: state.selectedCaseGroupUsers,
36
+ isCaseOwnerUpdating: state.isCaseOwnerUpdating,
35
37
  }), isEqual);
36
38
  const { routeState: { showValidationErrorAlert }, } = useContext(RouteContext);
37
39
  const caseDispatch = useCaseDispatch();
38
- const { globalMetadataState: { loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
40
+ const { globalMetadataState: { loggedInUserRights, loggedInUser }, } = useContext(GlobalMetadataStateContext);
39
41
  const previousAccountNumber = usePrevious(accountNumber);
40
- const [isCaseOwnerUpdating, setCaseOwnerUpdating] = useState(false);
41
42
  const [usersWithGroupAccess, setUsersWithGroupAccess] = useState([]);
42
43
  const [localOwnerChange, setLocalOwnerChange] = useState(false);
43
44
  const afterLocalChange = () => setLocalOwnerChange(false);
@@ -47,17 +48,70 @@ function OwnerSelector(props) {
47
48
  !isEmpty(pvalue.ssoUsername) &&
48
49
  value.ssoUsername !== pvalue.ssoUsername;
49
50
  const canEditCase = useCanEditCase();
51
+ const setContactPhoneNumber = (sso) => __awaiter(this, void 0, void 0, function* () {
52
+ if (sso === loggedInUser.data.ssoUsername) {
53
+ setCaseDetails(caseDispatch, {
54
+ phone: loggedInUser.data.phone,
55
+ suppliedPhoneNumberVerified: 'True',
56
+ });
57
+ }
58
+ else {
59
+ try {
60
+ const selectedContact = yield contacts.getSFDCContactBySso(sso);
61
+ setCaseDetails(caseDispatch, {
62
+ phone: selectedContact.phone,
63
+ suppliedPhoneNumberVerified: 'Deferred',
64
+ });
65
+ }
66
+ catch (e) {
67
+ setCaseDetails(caseDispatch, {
68
+ phone: '',
69
+ suppliedPhoneNumberVerified: 'Deferred',
70
+ });
71
+ }
72
+ }
73
+ });
74
+ const updateContactPhoneNumber = (sso) => __awaiter(this, void 0, void 0, function* () {
75
+ try {
76
+ if (sso === loggedInUser.data.ssoUsername) {
77
+ yield updateCaseDetails(caseDispatch, caseNumber, {
78
+ phone: loggedInUser.data.phone,
79
+ suppliedPhoneNumberVerified: 'Deferred',
80
+ });
81
+ }
82
+ else {
83
+ try {
84
+ const selectedContact = yield contacts.getSFDCContactBySso(sso);
85
+ yield updateCaseDetails(caseDispatch, caseNumber, {
86
+ phone: selectedContact.phone,
87
+ suppliedPhoneNumberVerified: 'Deferred',
88
+ });
89
+ }
90
+ catch (e) {
91
+ yield updateCaseDetails(caseDispatch, caseNumber, {
92
+ phone: '',
93
+ suppliedPhoneNumberVerified: 'Deferred',
94
+ });
95
+ }
96
+ }
97
+ ToastNotification.addSuccessMessage(t(`Phone number has been successfully updated`));
98
+ }
99
+ catch (e) {
100
+ caseUpdateError.showError(e, t(`Phone number failed to update`));
101
+ }
102
+ });
50
103
  /**
51
104
  * Changing selected owner related
52
105
  */
53
106
  const previousCaseOwner = usePrevious(selectedOwner.data.ssoUsername);
54
107
  const onOwnerChange = (selectedContact, prevCaseOwner, notificationContacts, dispatch, abortSignalCaseGroup, abortSignalEntitlements) => __awaiter(this, void 0, void 0, function* () {
55
- if (prevCaseOwner === selectedContact.ssoUsername)
108
+ if (prevCaseOwner === selectedContact.ssoUsername || isEmpty(selectedContact.ssoUsername))
56
109
  return;
57
110
  yield setCaseOwner(dispatch, selectedContact, '', abortSignalCaseGroup, abortSignalEntitlements, true);
58
111
  setLocalOwnerChange(true);
59
112
  !isEmpty(selectedContact) &&
60
113
  setNotifiedUser(dispatch, filter(notificationContacts, (c) => c.ssoUsername !== selectedContact.ssoUsername));
114
+ setContactPhoneNumber(selectedContact.ssoUsername);
61
115
  });
62
116
  /** Reset owner when selected account number changes */
63
117
  useEffect(() => {
@@ -90,7 +144,7 @@ function OwnerSelector(props) {
90
144
  };
91
145
  const onCaseOwnerUpdate = (newOwner) => __awaiter(this, void 0, void 0, function* () {
92
146
  const caseDetails = { contactSSOName: newOwner.ssoUsername };
93
- setCaseOwnerUpdating(true);
147
+ setCaseState(caseDispatch, { isCaseOwnerUpdating: true });
94
148
  try {
95
149
  yield updateCaseDetails(caseDispatch, caseNumber, caseDetails);
96
150
  const abortSignal = new AbortController().signal;
@@ -102,11 +156,12 @@ function OwnerSelector(props) {
102
156
  }, '', abortSignal);
103
157
  setLocalOwnerChange(true);
104
158
  updateNotifyUsersList(newOwner);
105
- setCaseOwnerUpdating(false);
159
+ yield updateContactPhoneNumber(newOwner.ssoUsername);
160
+ setCaseState(caseDispatch, { isCaseOwnerUpdating: false });
106
161
  ToastNotification.addSuccessMessage(t(`Owner has been successfully updated`));
107
162
  }
108
163
  catch (e) {
109
- setCaseOwnerUpdating(false);
164
+ setCaseState(caseDispatch, { isCaseOwnerUpdating: false });
110
165
  caseUpdateError.showError(e, t(`Owner failed to update`));
111
166
  }
112
167
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Case.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/Case.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAS,mBAAmB,EAAiD,MAAM,kBAAkB,CAAC;AAmB7G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC;CACnC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,KAAK,EAAE,MAAM,eAmLzC"}
1
+ {"version":3,"file":"Case.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/Case.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAS,mBAAmB,EAAiD,MAAM,kBAAkB,CAAC;AAmB7G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC;CACnC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,KAAK,EAAE,MAAM,eA6LzC"}
@@ -4,7 +4,7 @@ import { AbilityContext, CaseDetailsFields, resourceActions, resources } from '@
4
4
  import { getUrlParsedParams, isValidCaseNumber } from '@rh-support/utils';
5
5
  import isEmpty from 'lodash/isEmpty';
6
6
  import isEqual from 'lodash/isEqual';
7
- import React, { useContext, useEffect } from 'react';
7
+ import React, { useContext, useEffect, useRef } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
  import { Route, Switch, useLocation, useParams, useRouteMatch } from 'react-router-dom';
10
10
  import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
@@ -29,6 +29,7 @@ export default function Case(props) {
29
29
  const { caseNumber } = useParams();
30
30
  const queryParams = getUrlParsedParams(useLocation().search);
31
31
  const ability = useContext(AbilityContext);
32
+ const caseDetailsTabsRef = useRef(null);
32
33
  const canSeeFeedbackButtons = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_FEEDBACK_BUTTONS);
33
34
  const canReadCase = ability.can(resourceActions.READ, resources.CASE_DETAILS);
34
35
  const canSeeExternalTracker = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_EXTERNAL_TRACKER);
@@ -114,11 +115,11 @@ export default function Case(props) {
114
115
  canReadCase &&
115
116
  (!isFetchingCaseDetails || !isEmpty(product)) &&
116
117
  !isFetchingCaseDetailsError && (React.createElement(React.Fragment, null,
117
- React.createElement(ErrorBoundary, null,
118
- React.createElement(CaseOverview, { caseNumber: caseNumber })),
118
+ React.createElement(ErrorBoundary, { errorMsgInfo: t('There was an error loading cases. Please try refreshing the page.') },
119
+ React.createElement(CaseOverview, { caseNumber: caseNumber, tabsRef: caseDetailsTabsRef })),
119
120
  React.createElement(Switch, null,
120
121
  React.createElement(Route, { path: `${path}/:activeTab?` },
121
- React.createElement(CaseDetailsTabs, { basePath: url, caseNumber: caseNumber, routeProps: props.routeProps }))))),
122
+ React.createElement(CaseDetailsTabs, { basePath: url, caseNumber: caseNumber, routeProps: props.routeProps, tabdRef: caseDetailsTabsRef }))))),
122
123
  React.createElement(HostnameAwarenessModal, null))),
123
124
  React.createElement(CaseDetailsAside, { caseNumber: caseNumber }),
124
125
  React.createElement(CaseDetailsModals, { caseNumber: caseNumber, isSecureSupport: loggedInUsersAccount.data.secureSupport })))))));
@@ -196,7 +196,7 @@ export function CaseDetailsAside(props) {
196
196
  React.createElement(Checkbox, { label: t('Set to default'), isChecked: isDefaultBoxChecked, onChange: onDefaultCheckboxChange, id: "set-default-view-checkbox", name: "default-view-checkbox", isDisabled: isDefaultBoxChecked, className: 'defaultViewCheckbox' })))),
197
197
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading top solutions') } },
198
198
  React.createElement(CaseSolutions, { caseNumber: caseNumber, ref: topSolutionsRef, isSecureSupportAccount: isSecureSupportAccount })),
199
- !caseEscalations.isFetching && canViewACESection && (React.createElement(ErrorBoundary, null,
199
+ !caseEscalations.isFetching && canViewACESection && (React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading customer escalation') } },
200
200
  React.createElement(ActiveCustomerEscalation, { caseNumber: caseNumber, caseSeverity: severity, caseStatus: status, ref: createEscalationRef }))),
201
201
  isExternal && (React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading remote session agreement') } },
202
202
  React.createElement(RemoteSessionAgreement, { caseNumber: caseNumber, caseSeverity: severity, caseStatus: status, ref: createEscalationRef, acceptedRemoteSessionTerms: acceptedRemoteSessionTerms, readOnly: canReadCase })))))));
@@ -1,8 +1,10 @@
1
+ import React from 'react';
1
2
  import { RouteComponentProps } from 'react-router-dom';
2
3
  interface IProps {
3
4
  caseNumber: string;
4
5
  routeProps: RouteComponentProps;
5
6
  basePath: string;
7
+ tabdRef: React.MutableRefObject<HTMLDivElement>;
6
8
  }
7
9
  export declare function CaseDetailsTabs(props: IProps): JSX.Element;
8
10
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"CaseDetailsTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/CaseDetailsTabs.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AAwBlE,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,mBAAmB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;CACpB;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,eAiL5C"}
1
+ {"version":3,"file":"CaseDetailsTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/CaseDetailsTabs.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AAwBlE,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,mBAAmB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,eAmL5C"}
@@ -59,7 +59,7 @@ export function CaseDetailsTabs(props) {
59
59
  key: 'case details',
60
60
  routePath: 'management',
61
61
  ref: managementTabRef,
62
- component: React.createElement(CaseDetailsManagement, { caseNumber: caseNumber, routeProps: props.routeProps }),
62
+ component: (React.createElement(CaseDetailsManagement, { caseNumber: caseNumber, routeProps: props.routeProps, tabRef: managementTabRef })),
63
63
  });
64
64
  canSeeBugZillas &&
65
65
  tabsToRender.push({
@@ -104,7 +104,7 @@ export function CaseDetailsTabs(props) {
104
104
  return tabIndex > -1 ? tabIndex : activeTabKey;
105
105
  };
106
106
  const isTabVisibleInPdfExport = (tab) => tab.title === CaseDetailsTabsEnum.DISCUSSION && pdfOption === 'Reduced' ? false : true;
107
- return (React.createElement("div", { className: "case-details-tabs" },
107
+ return (React.createElement("div", { className: "case-details-tabs", ref: props.tabdRef },
108
108
  React.createElement(Tabs, { className: "hide-in-pdf", activeKey: getActiveTabKey(), component: TabsComponent.nav, onSelect: handleTabClick }, tabsToRender.map((tab, index) => (React.createElement(Tab, { eventKey: index, tabContentRef: tab.ref, tabContentId: tab.key, key: tab.title, href: `#${props.basePath}/${tab.routePath}`, "data-tracking-id": tab['data-tracking-id'], title: React.createElement(TabTitleText, null,
109
109
  React.createElement(Trans, null, tab.title)) })))),
110
110
  React.createElement("div", { className: "case-details-tabs-content pf-u-pt-xl" }, tabsToRender.map((tab, index) => (React.createElement(TabContent, { eventKey: index, key: tab.key, id: tab.key, ref: tab.ref, "aria-label": tab.title, hidden: isExportingPDF ? !isTabVisibleInPdfExport(tab) : index !== getActiveTabKey() },
@@ -4,7 +4,7 @@ import { CaseSecureSupportAlert } from './CaseSecureSupportAlert';
4
4
  import { CaseSubscriptionAbuseAlert } from './CaseSubscriptionAbuseAlert';
5
5
  export function CaseDetailsWarningMessage(props) {
6
6
  const subscriptionAbused = useSubscriptionAbused();
7
- return (React.createElement("div", { className: "pf-u-mb-md" },
7
+ return (React.createElement(React.Fragment, null,
8
8
  React.createElement(CaseSecureSupportAlert, { caseNumber: props.caseNumber, selectedAccountDetails: props.selectedAccountDetails }),
9
9
  subscriptionAbused.isAccountFreezed && React.createElement(CaseSubscriptionAbuseAlert, null)));
10
10
  }
@@ -1,5 +1,7 @@
1
+ import React from 'react';
1
2
  interface IProps {
2
3
  caseNumber: string;
4
+ tabsRef: React.MutableRefObject<HTMLDivElement>;
3
5
  }
4
6
  export default function CaseOverview(props: IProps): JSX.Element;
5
7
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseEditView/CaseOverview/index.tsx"],"names":[],"mappings":"AAyCA,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,EAAE,MAAM,eAoejD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseEditView/CaseOverview/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA8D,MAAM,OAAO,CAAC;AA6BnF,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AAED,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,KAAK,EAAE,MAAM,eAqejD"}
@@ -26,6 +26,7 @@ import { usePostComment } from '../../shared/usePostComment';
26
26
  import { ReopenCaseModal } from '../ConfirmationModals/ReopenCaseModal';
27
27
  import { PDFContext } from '../PDFContainer';
28
28
  import { CaseInformation } from '../Tabs/CaseDetails/CaseInformation';
29
+ import { CaseContactPhoneNumberAlert } from '../Tabs/CaseDetails/CasePhoneNumberConfirmAlert';
29
30
  import Summary from '../Tabs/CaseDetails/Summary';
30
31
  import CaseOwnerInfo from './CaseOwnerInfo';
31
32
  import CaseStatus from './CaseStatus';
@@ -224,6 +225,7 @@ export default function CaseOverview(props) {
224
225
  React.createElement(Trans, null, "Case inactivity warning")),
225
226
  React.createElement("p", { className: "pf-u-mb-sm" },
226
227
  React.createElement(Trans, null, "The customer has received two warnings regarding inactivity. This case will be closed soon if we don't receive any input."))) })))),
228
+ React.createElement(CaseContactPhoneNumberAlert, { isReview: true, tabRef: props.tabsRef }),
227
229
  React.createElement("header", null,
228
230
  React.createElement("h2", { className: "case-ID" },
229
231
  React.createElement(Trans, null, "Case"),
@@ -1 +1 @@
1
- {"version":3,"file":"CaseSecureSupportAlert.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/CaseSecureSupportAlert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AAOlE,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,EAAE,QAAQ,CAAC;CACpC;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,eAyBnD"}
1
+ {"version":3,"file":"CaseSecureSupportAlert.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/CaseSecureSupportAlert.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wCAAwC,CAAC;AAOlE,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,EAAE,QAAQ,CAAC;CACpC;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,eA+BnD"}
@@ -17,6 +17,6 @@ export function CaseSecureSupportAlert(props) {
17
17
  "to access secure support cases."));
18
18
  }
19
19
  };
20
- return (React.createElement(AlertMessage, { variant: AlertType.WARNING, show: isSecureSupportTechViewingSecureCase, isInline: true },
20
+ return (React.createElement(AlertMessage, { className: "pf-u-mb-md", variant: AlertType.WARNING, show: isSecureSupportTechViewingSecureCase, isInline: true },
21
21
  React.createElement(Trans, null, getWarningMsg())));
22
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CaseAlternateId.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseAlternateId.tsx"],"names":[],"mappings":"AAiBA,UAAU,MAAM;IACZ,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAOD,iBAAS,eAAe,CAAC,KAAK,EAAE,MAAM,eAqIrC;kBArIQ,eAAe;;;AAwIxB,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"CaseAlternateId.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseAlternateId.tsx"],"names":[],"mappings":"AA2BA,UAAU,MAAM;IACZ,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAOD,iBAAS,eAAe,CAAC,KAAK,EAAE,MAAM,eA0KrC;kBA1KQ,eAAe;;;AA6KxB,eAAe,eAAe,CAAC"}
@@ -7,11 +7,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { Tooltip, TooltipPosition } from '@patternfly/react-core';
10
+ import { InputGroupText, InputGroupTextVariant, Spinner, TextInput, TextInputGroup, Tooltip, TooltipPosition, ValidatedOptions, } from '@patternfly/react-core';
11
+ import CheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon';
11
12
  import InfoIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
12
- import { InlineEdit, LoadingIndicator, ToastNotification, ValueChangedIcon } from '@rh-support/components';
13
+ import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
14
+ import { NewInlineEdit, ToastNotification, ValueChangedIcon } from '@rh-support/components';
13
15
  import { useCanEditCase } from '@rh-support/react-context';
14
- import isEmpty from 'lodash/isEmpty';
15
16
  import isEqual from 'lodash/isEqual';
16
17
  import React, { useEffect, useState } from 'react';
17
18
  import { Trans, useTranslation } from 'react-i18next';
@@ -23,7 +24,7 @@ import { CaseValuesToWatch } from '../../../shared/Constants';
23
24
  import { getChangedValueTooltip } from '../../../shared/utils';
24
25
  const defaultProps = {
25
26
  inlineEditable: true,
26
- hideSaveCancel: false,
27
+ hideSaveCancel: true,
27
28
  };
28
29
  function CaseAlternateId(props) {
29
30
  const { t } = useTranslation();
@@ -39,18 +40,22 @@ function CaseAlternateId(props) {
39
40
  const [localAltIDChange, setLocalAltIDChange] = useState(false);
40
41
  const afterLocalChange = () => setLocalAltIDChange(false);
41
42
  const canEditCase = useCanEditCase();
43
+ // To keep track of Cancel button state to close InlineEdit input mode
44
+ const [isCancelClicked, setIsCancelClicked] = useState(false);
45
+ // To keep track of Save button state to close InlineEdit input mode
46
+ const [isSaveClicked, setIsSaveClicked] = useState(false);
42
47
  useEffect(() => {
43
48
  if (alternateId !== alternateIdState) {
44
49
  setAlternateIdState(alternateId);
45
50
  }
46
51
  // eslint-disable-next-line react-hooks/exhaustive-deps
47
52
  }, [alternateId]);
48
- const onAlternateIdChange = (e) => {
49
- var _a;
53
+ // Function to handle when Alternate ID changes
54
+ const onAlternateIdChange = (value) => {
50
55
  if (canEditCase.alert())
51
56
  return;
52
- setAlternateIdState(e.target.value);
53
- !caseNumber && setCaseDetails(caseDispatch, { alternateId: (_a = e.target.value) === null || _a === void 0 ? void 0 : _a.trim() });
57
+ setAlternateIdState(value);
58
+ !caseNumber && setCaseDetails(caseDispatch, { alternateId: value === null || value === void 0 ? void 0 : value.trim() });
54
59
  };
55
60
  const updateAlternateId = () => __awaiter(this, void 0, void 0, function* () {
56
61
  try {
@@ -71,32 +76,45 @@ function CaseAlternateId(props) {
71
76
  yield updateAlternateId();
72
77
  }
73
78
  setLocalAltIDChange(true);
79
+ setIsSaveClicked(!isSaveClicked);
74
80
  });
75
81
  const onCancel = () => {
76
82
  setAlternateIdState(alternateId);
83
+ setIsCancelClicked(!isCancelClicked);
77
84
  };
78
85
  const maxLengthErrorMessage = t('Alternate case ID cannot be more than {{limit}} characters.', {
79
86
  limit: ALTERNATE_CASE_ID_LIMIT,
80
87
  });
81
- // To check if alternate ID is empty
82
- const isAlternateIDEmpty = isEmpty(alternateIdState === null || alternateIdState === void 0 ? void 0 : alternateIdState.trim());
83
- // To populate the unsaved alternateId field with the previously saved value on onBlur event.
84
- const onBlur = () => {
85
- if (alternateId !== alternateIdState) {
86
- setAlternateIdState(alternateId);
88
+ // Conditions to disable save button
89
+ const saveDisabled = alternateIdState === alternateId || isUpdating || (alternateIdState === null || alternateIdState === void 0 ? void 0 : alternateIdState.length) > ALTERNATE_CASE_ID_LIMIT;
90
+ // Function to handle keyDown events
91
+ const handleKeyDown = (e) => __awaiter(this, void 0, void 0, function* () {
92
+ // Cancel on pressing esc
93
+ if (e.keyCode === 27) {
94
+ yield onCancel();
87
95
  }
88
- };
96
+ // Save on pressing enter
97
+ else if (!saveDisabled && e.keyCode === 13) {
98
+ yield onSave();
99
+ }
100
+ });
89
101
  return (React.createElement(React.Fragment, null,
90
- React.createElement(InlineEdit, { labelProps: { htmlFor: 'case-details-alternate-id' }, labelContent: React.createElement(React.Fragment, null,
102
+ React.createElement(NewInlineEdit, { labelProps: { htmlFor: 'case-details-alternate-id' }, labelContent: React.createElement(React.Fragment, null,
91
103
  React.createElement(Trans, null, "Alternate case ID"),
92
104
  React.createElement(ValueChangedIcon, { afterLocalChange: afterLocalChange, isLocalChange: localAltIDChange, value: alternateId, getTooltipContent: getChangedValueTooltip(() => CaseValuesToWatch.altID) }),
93
105
  ' ',
94
106
  React.createElement(Tooltip, { trigger: 'mouseenter focus', position: TooltipPosition.top, content: React.createElement(Trans, null, "Add your internal tracking ID to better identify and organize support issues.") },
95
- React.createElement(InfoIcon, { className: "pf-u-ml-sm", "aria-label": "Case Alternate ID" }))), allowInlineEdit: props.inlineEditable, content: alternateId, initialIsEditing: true, hideSaveCancel: props.hideSaveCancel, onSave: onSave, onCancel: onCancel, saveDisabled: isAlternateIDEmpty ||
96
- alternateIdState === alternateId ||
97
- isUpdating ||
98
- (alternateIdState === null || alternateIdState === void 0 ? void 0 : alternateIdState.length) > ALTERNATE_CASE_ID_LIMIT, loadingIndicator: isUpdating ? React.createElement(LoadingIndicator, { isInline: true }) : null },
99
- React.createElement("input", { value: alternateIdState, type: "text", className: "form-control", id: "case-details-alternate-id", placeholder: t(`Enter your case tracking number or internal incident ID`), onChange: onAlternateIdChange, disabled: isUpdating, "data-tracking-id": "case-details-alternate-id", onBlur: onBlur })),
107
+ React.createElement(InfoIcon, { className: "pf-u-ml-sm", "aria-label": "Case Alternate ID" }))), allowInlineEdit: props.inlineEditable, content: alternateId || t('No Alternate case ID to display.'), hideSaveCancel: props.hideSaveCancel, saveDisabled: saveDisabled, charCount: (alternateIdState === null || alternateIdState === void 0 ? void 0 : alternateIdState.length) || 0, charTotal: ALTERNATE_CASE_ID_LIMIT, cancelToggleState: isCancelClicked, saveToggleState: isSaveClicked },
108
+ React.createElement(TextInputGroup, null,
109
+ React.createElement(TextInput, { value: alternateIdState, type: "text", className: "form-control", id: "case-details-alternate-id", placeholder: t(`Enter your case tracking number or internal incident ID`), onChange: onAlternateIdChange, "data-tracking-id": "case-details-alternate-id", isDisabled: isUpdating, onKeyDown: handleKeyDown, validated: (alternateIdState === null || alternateIdState === void 0 ? void 0 : alternateIdState.length) > ALTERNATE_CASE_ID_LIMIT
110
+ ? ValidatedOptions.error
111
+ : ValidatedOptions.default }),
112
+ !isUpdating ? (React.createElement(InputGroupText, { variant: InputGroupTextVariant.plain },
113
+ React.createElement("button", { className: "btn btn-app btn-link pf-u-ml-sm", type: "button", disabled: saveDisabled, onClick: onSave },
114
+ React.createElement(CheckIcon, null)),
115
+ React.createElement("button", { className: "btn btn-app btn-link", type: "button", onClick: onCancel },
116
+ React.createElement(TimesIcon, { color: "#6A6E73" })))) : (React.createElement(InputGroupText, { variant: InputGroupTextVariant.plain },
117
+ React.createElement(Spinner, { isSVG: true, size: "lg", className: "pf-u-ml-2xl pf-u-mr-xl" }))))),
100
118
  (alternateIdState === null || alternateIdState === void 0 ? void 0 : alternateIdState.length) > ALTERNATE_CASE_ID_LIMIT && (React.createElement("div", { className: "pull-top" },
101
119
  React.createElement("p", { className: "form-instructions form-invalid" },
102
120
  React.createElement(Trans, null, maxLengthErrorMessage))))));
@@ -0,0 +1,2 @@
1
+ export declare function CaseContactPhoneNumber(): JSX.Element;
2
+ //# sourceMappingURL=CaseContactPhoneNumber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CaseContactPhoneNumber.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,sBAAsB,gBA2IrC"}
@@ -0,0 +1,95 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { InputGroupText, InputGroupTextVariant, Spinner, TextInput, TextInputGroup, ValidatedOptions, } from '@patternfly/react-core';
11
+ import CheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon';
12
+ import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
13
+ import { NewInlineEdit, ToastNotification } from '@rh-support/components';
14
+ import { GlobalMetadataStateContext, useCanEditCase } from '@rh-support/react-context';
15
+ import isEqual from 'lodash/isEqual';
16
+ import React, { useContext, useEffect, useState } from 'react';
17
+ import { Trans, useTranslation } from 'react-i18next';
18
+ import { PHONE_INSTRUCTION } from '../../../../constants/caseDetailsConstants';
19
+ import { useCaseDispatch, useCaseSelector } from '../../../../context/CaseContext';
20
+ import { useCaseUpdateErrorMessage } from '../../../../hooks/useCaseUpdateErrorMessage';
21
+ import { PHONE_LIMIT } from '../../../../reducers/CaseConstNTypes';
22
+ import { updateCaseDetails } from '../../../../reducers/CaseReducer';
23
+ import { ContactPhoneNumberPopOver } from '../../../CaseInformation/ContactPhoneNumberPopOver';
24
+ export function CaseContactPhoneNumber() {
25
+ const { phone, caseNumber, contactSSOName, suppliedPhoneNumberVerified, isCaseOwnerUpdating } = useCaseSelector((state) => ({
26
+ phone: state.caseDetails.phone || '',
27
+ caseNumber: state.caseDetails.caseNumber,
28
+ contactSSOName: state.caseDetails.contactSSOName,
29
+ suppliedPhoneNumberVerified: state.caseDetails.suppliedPhoneNumberVerified,
30
+ isCaseOwnerUpdating: state.isCaseOwnerUpdating,
31
+ }), isEqual);
32
+ const { globalMetadataState: { loggedInUser }, } = useContext(GlobalMetadataStateContext);
33
+ const canEditCase = useCanEditCase();
34
+ const [isCasePhoneUpdating, setCasePhoneUpdating] = useState(false);
35
+ const [localPhoneState, setLocalPhoneState] = useState(phone);
36
+ const caseDispatch = useCaseDispatch();
37
+ const caseUpdateError = useCaseUpdateErrorMessage();
38
+ const { t } = useTranslation();
39
+ const onPhoneChange = (phone) => __awaiter(this, void 0, void 0, function* () {
40
+ if (canEditCase.alert())
41
+ return;
42
+ setLocalPhoneState(phone);
43
+ });
44
+ const onSave = () => __awaiter(this, void 0, void 0, function* () {
45
+ setCasePhoneUpdating(true);
46
+ try {
47
+ yield updateCaseDetails(caseDispatch, caseNumber, { phone: localPhoneState.trim() });
48
+ setCasePhoneUpdating(false);
49
+ ToastNotification.addSuccessMessage(t(`Phone number has been successfully updated`));
50
+ }
51
+ catch (e) {
52
+ setCasePhoneUpdating(false);
53
+ caseUpdateError.showError(e, t(`Phone number failed to update`));
54
+ }
55
+ });
56
+ const onCancel = () => {
57
+ setLocalPhoneState(phone);
58
+ };
59
+ // Function to handle keyDown events
60
+ const handleKeyDown = (e) => __awaiter(this, void 0, void 0, function* () {
61
+ // Cancel on pressing esc
62
+ if (e.keyCode === 27) {
63
+ yield onCancel();
64
+ }
65
+ // Save on pressing enter
66
+ else if (!isCasePhoneUpdating && e.keyCode === 13) {
67
+ yield onSave();
68
+ }
69
+ });
70
+ useEffect(() => {
71
+ setLocalPhoneState(phone);
72
+ }, [phone]);
73
+ const maxLengthErrorMessage = t('Phone number cannot be more than {{limit}} characters.', {
74
+ limit: PHONE_LIMIT,
75
+ });
76
+ const isPhoneNeedsReview = contactSSOName === loggedInUser.data.ssoUsername && suppliedPhoneNumberVerified === 'Deferred';
77
+ return (React.createElement("div", { className: "form-group", style: { minWidth: '200px' } },
78
+ React.createElement(NewInlineEdit, { labelProps: { htmlFor: 'case-details-supplied-phone' }, labelContent: React.createElement(React.Fragment, null,
79
+ React.createElement(Trans, null, "Case owner's phone number"),
80
+ ContactPhoneNumberPopOver()), allowInlineEdit: false, hideSaveCancel: false, saveDisabled: isCasePhoneUpdating },
81
+ React.createElement(TextInputGroup, null,
82
+ React.createElement(TextInput, { value: localPhoneState || '', type: "text", className: "form-control", id: "case-details-supplied-phone", placeholder: "+1 555-555-5555", onChange: onPhoneChange, "data-tracking-id": "case-details-page-supplied-phone", isDisabled: isCasePhoneUpdating || isCaseOwnerUpdating, onKeyDown: handleKeyDown, validated: (localPhoneState === null || localPhoneState === void 0 ? void 0 : localPhoneState.length) > PHONE_LIMIT
83
+ ? ValidatedOptions.error
84
+ : isPhoneNeedsReview
85
+ ? ValidatedOptions.warning
86
+ : ValidatedOptions.default }),
87
+ !isCasePhoneUpdating ? (React.createElement(InputGroupText, { variant: InputGroupTextVariant.plain },
88
+ React.createElement("button", { className: "btn btn-app btn-link pf-u-ml-sm", type: "button", "data-tracking-id": "case-details-page-supplied-phone-save", onClick: () => onSave(), disabled: (localPhoneState === null || localPhoneState === void 0 ? void 0 : localPhoneState.length) > PHONE_LIMIT || localPhoneState === phone },
89
+ React.createElement(CheckIcon, null)),
90
+ React.createElement("button", { className: "btn btn-app btn-link", type: "button", onClick: onCancel, "data-tracking-id": "case-details-page-supplied-phone-cancel" },
91
+ React.createElement(TimesIcon, { color: "#6A6E73" })))) : (React.createElement(InputGroupText, { variant: InputGroupTextVariant.plain },
92
+ React.createElement(Spinner, { isSVG: true, size: "lg", className: "pf-u-ml-2xl pf-u-mr-xl" })))),
93
+ (localPhoneState === null || localPhoneState === void 0 ? void 0 : localPhoneState.length) > PHONE_LIMIT ? (React.createElement("p", { className: "form-instructions form-invalid" }, maxLengthErrorMessage)) : (React.createElement("p", { className: "form-instructions" },
94
+ React.createElement(Trans, null, PHONE_INSTRUCTION))))));
95
+ }
@@ -1,8 +1,10 @@
1
1
  import { IDClassNameProps } from '@rh-support/types/shared';
2
+ import React from 'react';
2
3
  import { RouteComponentProps } from 'react-router';
3
4
  interface IProps extends IDClassNameProps {
4
5
  caseNumber: string;
5
6
  routeProps: RouteComponentProps;
7
+ tabRef: React.MutableRefObject<HTMLDivElement>;
6
8
  }
7
9
  export default function CaseDetailsManagement(props: IProps): JSX.Element;
8
10
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"CaseDetailsManagement.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseDetailsManagement.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAenD,UAAU,MAAO,SAAQ,gBAAgB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,mBAAmB,CAAC;CACnC;AAED,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,KAAK,EAAE,MAAM,eAyD1D"}
1
+ {"version":3,"file":"CaseDetailsManagement.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseDetailsManagement.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,OAAO,KAA+B,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAiBnD,UAAU,MAAO,SAAQ,gBAAgB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,mBAAmB,CAAC;IAChC,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CAClD;AAED,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAAC,KAAK,EAAE,MAAM,eAiE1D"}
@@ -1,3 +1,4 @@
1
+ import { Flex, FlexItem } from '@patternfly/react-core';
1
2
  import { AbilityContext, CaseDetailsFields, resourceActions, resources } from '@rh-support/user-permissions';
2
3
  import isEqual from 'lodash/isEqual';
3
4
  import React, { useContext, useState } from 'react';
@@ -11,7 +12,9 @@ import CaseContactSelector from '../../../CaseManagement/SendNotifications/CaseC
11
12
  import { PartnerCaseHelper } from '../../ShareCase/PartnerCaseHelper';
12
13
  import { ShareWithPartner } from '../../ShareCase/PartnerShare';
13
14
  import CaseAlternateId from './CaseAlternateId';
15
+ import { CaseContactPhoneNumber } from './CaseContactPhoneNumber';
14
16
  import CaseInternalStatus from './CaseInternalStatus';
17
+ import { CaseContactPhoneNumberAlert } from './CasePhoneNumberConfirmAlert';
15
18
  import CaseSbrGroups from './CaseSbrGroups';
16
19
  export default function CaseDetailsManagement(props) {
17
20
  const [isUpdatingPartner, setIsUpdatingPartner] = useState(false);
@@ -30,7 +33,12 @@ export default function CaseDetailsManagement(props) {
30
33
  React.createElement(PartnerCaseHelper, { setIsUpdatingPartners: setIsUpdatingPartner, caseNumber: props.caseNumber, routeProps: props.routeProps }),
31
34
  React.createElement("section", { className: "card card-white" },
32
35
  React.createElement("form", { onSubmit: handleFormSubmit },
33
- React.createElement(OwnerSelector, null),
36
+ React.createElement(Flex, { direction: { default: 'column', '2xl': 'row' } },
37
+ React.createElement(FlexItem, { flex: { default: 'flex_1' } },
38
+ React.createElement(OwnerSelector, null)),
39
+ React.createElement(FlexItem, { flex: { default: 'flex_1' } },
40
+ React.createElement(CaseContactPhoneNumber, null))),
41
+ React.createElement(CaseContactPhoneNumberAlert, { isConfirm: true }),
34
42
  canSeeInternalStatus && React.createElement(CaseInternalStatus, null),
35
43
  canSeeSBRGroups && React.createElement(CaseSbrGroups, null),
36
44
  React.createElement(CaseGroup, null),
@@ -1 +1 @@
1
- {"version":3,"file":"CaseHostname.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseHostname.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAa5D,UAAU,MAAO,SAAQ,gBAAgB;IACrC,cAAc,EAAE,OAAO,CAAC;CAC3B;AAMD,iBAAS,YAAY,CAAC,KAAK,EAAE,MAAM,eAwKlC;kBAxKQ,YAAY;;;AA2KrB,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"CaseHostname.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseHostname.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAY5D,UAAU,MAAO,SAAQ,gBAAgB;IACrC,cAAc,EAAE,OAAO,CAAC;CAC3B;AAMD,iBAAS,YAAY,CAAC,KAAK,EAAE,MAAM,eAqKlC;kBArKQ,YAAY;;;AAwKrB,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -12,7 +12,6 @@ import { Popover, PopoverPosition, Spinner, Switch } from '@patternfly/react-cor
12
12
  import { InlineEdit, LoadingIndicator, ToastNotification, useFetch, ValueChangedIcon } from '@rh-support/components';
13
13
  import { GlobalMetadataStateContext, useCanEditCase } from '@rh-support/react-context';
14
14
  import { ability, CaseListFields, resourceActions, resources } from '@rh-support/user-permissions';
15
- import isEmpty from 'lodash/isEmpty';
16
15
  import isEqual from 'lodash/isEqual';
17
16
  import React, { useContext, useEffect, useState } from 'react';
18
17
  import { Trans, useTranslation } from 'react-i18next';
@@ -105,13 +104,11 @@ function CaseHostname(props) {
105
104
  return React.createElement(React.Fragment, null);
106
105
  }
107
106
  const lengthError = (hostnameState === null || hostnameState === void 0 ? void 0 : hostnameState.length) > HOSTNAME_LENGTH_LIMIT;
108
- // To check if host name is empty
109
- const isHostNameEmpty = isEmpty(hostnameState === null || hostnameState === void 0 ? void 0 : hostnameState.trim());
110
107
  return (React.createElement(React.Fragment, null,
111
108
  React.createElement(InlineEdit, { labelProps: { htmlFor: 'case-details-hostname' }, formClassName: props.className || '', labelContent: React.createElement(React.Fragment, null,
112
109
  React.createElement(Trans, null, "Hostname"),
113
110
  React.createElement(ValueChangedIcon, { afterLocalChange: afterLocalChange, isLocalChange: localHostnameChange, value: hostname, getTooltipContent: getChangedValueTooltip(() => CaseValuesToWatch.hostname) })), helperContent: React.createElement(Popover, { "aria-label": "Hostname Info", position: PopoverPosition.auto, bodyContent: hostNameVisibilityContent, closeBtnAriaLabel: "Close", headerContent: 'Share hostname?', onShow: () => userOriginalHostnameValue() },
114
- React.createElement("i", { "aria-label": "Hostname Info", className: "m-l-1 fa fa-question-circle" })), allowInlineEdit: props.inlineEditable, content: hostname, saveDisabled: isHostNameEmpty || hostnameState === hostname || isHostnameUpdating || lengthError, onSave: onSave, onCancel: onCancel, initialIsEditing: false, loadingIndicator: isHostnameUpdating ? React.createElement(LoadingIndicator, { show: isHostnameUpdating, isInline: true }) : null },
111
+ React.createElement("i", { "aria-label": "Hostname Info", className: "m-l-1 fa fa-question-circle" })), allowInlineEdit: props.inlineEditable, content: hostname, saveDisabled: hostnameState === hostname || isHostnameUpdating || lengthError, onSave: onSave, onCancel: onCancel, initialIsEditing: false, loadingIndicator: isHostnameUpdating ? React.createElement(LoadingIndicator, { show: isHostnameUpdating, isInline: true }) : undefined },
115
112
  React.createElement("input", { type: "text", id: "case-details-hostname", className: `form-control${lengthError ? ' form-invalid' : ''}`, name: "case-details-hostname", value: hostnameState, onChange: onHostnameChange, disabled: isHostnameUpdating, "data-tracking-id": "case-details-hostname", "aria-invalid": lengthError })),
116
113
  lengthError && (React.createElement("div", { className: "pull-top" },
117
114
  React.createElement("p", { className: "form-instructions form-invalid" },
@@ -1 +1 @@
1
- {"version":3,"file":"CaseOpenshiftClusterId.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.tsx"],"names":[],"mappings":"AA2BA,wBAAgB,sBAAsB,gBA8RrC"}
1
+ {"version":3,"file":"CaseOpenshiftClusterId.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.tsx"],"names":[],"mappings":"AA2BA,wBAAgB,sBAAsB,gBAgSrC"}
@@ -50,6 +50,7 @@ export function CaseOpenshiftClusterId() {
50
50
  const displayName = useRef('');
51
51
  const previousLocalOpenshiftClusterIDState = usePrevious(localOpenshiftClusterIDState);
52
52
  const previousSelectedReason = usePrevious(selectedReason);
53
+ const previousProduct = usePrevious(product);
53
54
  const { t } = useTranslation();
54
55
  const clusterStateReset = () => {
55
56
  setSelectedReason('');
@@ -72,7 +73,8 @@ export function CaseOpenshiftClusterId() {
72
73
  const hasCluster = yield isClusterIdEnabledForProduct(product, (_b = allProducts.data) === null || _b === void 0 ? void 0 : _b.productsResult);
73
74
  setShowClusterId(hasCluster);
74
75
  // when product changes from a product with cluster to a product without cluster, reset the clusterId
75
- const isResetClusterID = !hasCluster || isOpenShiftV3;
76
+ const IsProductHasChanged = previousProduct && previousProduct !== product;
77
+ const isResetClusterID = (!hasCluster || isOpenShiftV3) && IsProductHasChanged;
76
78
  if (isResetClusterID) {
77
79
  const caseDetails = {
78
80
  openshiftClusterID: '',