@rh-support/troubleshoot 2.2.120 → 2.2.122

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 (41) hide show
  1. package/lib/esm/components/AccountInfo/OwnerSelector.d.ts.map +1 -1
  2. package/lib/esm/components/AccountInfo/OwnerSelector.js +49 -12
  3. package/lib/esm/components/CaseEditView/CaseDetailsTabs.d.ts.map +1 -1
  4. package/lib/esm/components/CaseEditView/CaseDetailsTabs.js +11 -0
  5. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.d.ts.map +1 -1
  6. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.js +76 -33
  7. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.d.ts.map +1 -1
  8. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.js +6 -2
  9. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberSev1ConfirmAlert.d.ts.map +1 -1
  10. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberSev1ConfirmAlert.js +7 -3
  11. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseExternalTrackerUpdate.js +1 -1
  12. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/CaseHistory.css +0 -0
  13. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/CaseHistory.d.ts +4 -2
  14. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/CaseHistory.d.ts.map +1 -1
  15. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/CaseHistory.js +7 -3
  16. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.css +257 -0
  17. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.d.ts +7 -0
  18. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.d.ts.map +1 -0
  19. package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.js +236 -0
  20. package/lib/esm/components/CaseInformation/ContactPhoneNumber.d.ts.map +1 -1
  21. package/lib/esm/components/CaseInformation/ContactPhoneNumber.js +32 -20
  22. package/lib/esm/components/CaseInformation/ContactPhoneNumberAlert.d.ts.map +1 -1
  23. package/lib/esm/components/CaseInformation/ContactPhoneNumberAlert.js +29 -7
  24. package/lib/esm/components/CaseInformation/Severity.d.ts.map +1 -1
  25. package/lib/esm/components/CaseInformation/Severity.js +0 -1
  26. package/lib/esm/components/ProductSelector/NewProductDropdownSelector.js +1 -1
  27. package/lib/esm/components/SessionRestore/SessionRestore.d.ts.map +1 -1
  28. package/lib/esm/components/SessionRestore/SessionRestore.js +1 -24
  29. package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.d.ts.map +1 -1
  30. package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.js +2 -0
  31. package/lib/esm/components/shared/utils.js +5 -5
  32. package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.d.ts.map +1 -1
  33. package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.js +8 -0
  34. package/lib/esm/constants/caseDetailsConstants.d.ts +2 -1
  35. package/lib/esm/constants/caseDetailsConstants.d.ts.map +1 -1
  36. package/lib/esm/constants/caseDetailsConstants.js +1 -0
  37. package/lib/esm/reducers/CaseConstNTypes.d.ts +2 -0
  38. package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
  39. package/lib/esm/reducers/CaseConstNTypes.js +2 -0
  40. package/lib/esm/scss/_pf-overrides.scss +4 -0
  41. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"OwnerSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/AccountInfo/OwnerSelector.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAkB/D,UAAU,MAAM;CAAG;AAEnB,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,qBA2VnC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"OwnerSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/AccountInfo/OwnerSelector.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAkB/D,UAAU,MAAM;CAAG;AAEnB,iBAAS,aAAa,CAAC,KAAK,EAAE,MAAM,qBAqYnC;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -28,7 +28,7 @@ import { getChangedValueTooltip } from '../shared/utils';
28
28
  function OwnerSelector(props) {
29
29
  const { t } = useTranslation();
30
30
  const caseUpdateError = useCaseUpdateErrorMessage();
31
- const { accountNumber, caseNumber, selectedNotificationContacts, selectedOwner, selectedCaseGroupUsers, isCaseOwnerUpdating, caseDetailes, } = useCaseSelector((state) => ({
31
+ const { accountNumber, caseNumber, selectedNotificationContacts, selectedOwner, selectedCaseGroupUsers, isCaseOwnerUpdating, caseDetailes, hasLoggedInUserConfirmedPhoneNumber, } = useCaseSelector((state) => ({
32
32
  accountNumber: state.caseDetails.accountNumberRef,
33
33
  caseNumber: state.caseDetails.caseNumber,
34
34
  selectedNotificationContacts: state.selectedNotificationContacts,
@@ -36,6 +36,7 @@ function OwnerSelector(props) {
36
36
  selectedCaseGroupUsers: state.selectedCaseGroupUsers,
37
37
  isCaseOwnerUpdating: state.isCaseOwnerUpdating,
38
38
  caseDetailes: state.caseDetails,
39
+ hasLoggedInUserConfirmedPhoneNumber: state.hasLoggedInUserConfirmedPhoneNumber,
39
40
  }), isEqual);
40
41
  const { routeState: { isNextBtnClickedToShowValidationError }, } = useContext(RouteContext);
41
42
  const caseDispatch = useCaseDispatch();
@@ -59,7 +60,10 @@ function OwnerSelector(props) {
59
60
  setCaseDetails(caseDispatch, {
60
61
  phoneAreaCodePrefixLineNumber: loggedInUser.data.supportPhoneAreaCodePrefixLineNumber,
61
62
  phoneCountryCode: loggedInUser.data.supportPhoneCountryCode,
62
- suppliedPhoneNumberVerified: 'True',
63
+ suppliedPhoneNumberVerified: isEqual(hasLoggedInUserConfirmedPhoneNumber, 'True') || //hasLoggedInUserConfirmedPhoneNumber: global verification phone state for contactSSOName === loggedInUser.data.ssoUsername
64
+ isEqual(hasLoggedInUserConfirmedPhoneNumber, 'Deferred')
65
+ ? hasLoggedInUserConfirmedPhoneNumber
66
+ : 'False',
63
67
  });
64
68
  }
65
69
  else {
@@ -68,7 +72,10 @@ function OwnerSelector(props) {
68
72
  setCaseDetails(caseDispatch, {
69
73
  phoneAreaCodePrefixLineNumber: phoneLine,
70
74
  phoneCountryCode: countryCode,
71
- suppliedPhoneNumberVerified: phoneLine && countryCode ? 'True' : 'False',
75
+ suppliedPhoneNumberVerified: isEqual(hasLoggedInUserConfirmedPhoneNumber, 'True') ||
76
+ isEqual(hasLoggedInUserConfirmedPhoneNumber, 'Deferred')
77
+ ? hasLoggedInUserConfirmedPhoneNumber
78
+ : 'False',
72
79
  });
73
80
  }
74
81
  }
@@ -101,7 +108,7 @@ function OwnerSelector(props) {
101
108
  });
102
109
  const updatePhone = (phoneSetting) => __awaiter(this, void 0, void 0, function* () {
103
110
  yield updateCaseDetails(caseDispatch, caseNumber, phoneSetting);
104
- setCaseDetails(caseDispatch, Object.assign(Object.assign({}, caseDetailes), phoneSetting));
111
+ setCaseDetails(caseDispatch, Object.assign({}, phoneSetting));
105
112
  });
106
113
  // set owner on updating a case
107
114
  const updateContactPhoneNumber = (sso) => __awaiter(this, void 0, void 0, function* () {
@@ -109,18 +116,25 @@ function OwnerSelector(props) {
109
116
  // logged in user and case owner are the same
110
117
  if (sso === loggedInUser.data.ssoUsername) {
111
118
  try {
112
- if (loggedInUser.data.supportPhoneAreaCodePrefixLineNumber) {
119
+ const loggedInUserContact = yield (contacts === null || contacts === void 0 ? void 0 : contacts.getSFDCContactBySso(sso)); // to get updated loggedIn user contact details
120
+ if (loggedInUserContact.supportPhoneAreaCodePrefixLineNumber) {
113
121
  yield updatePhone({
114
- phoneAreaCodePrefixLineNumber: loggedInUser.data.supportPhoneAreaCodePrefixLineNumber,
115
- phoneCountryCode: loggedInUser.data.supportPhoneCountryCode,
116
- suppliedPhoneNumberVerified: 'True',
122
+ phoneAreaCodePrefixLineNumber: loggedInUserContact.supportPhoneAreaCodePrefixLineNumber || '',
123
+ phoneCountryCode: loggedInUserContact.supportPhoneCountryCode || '',
124
+ suppliedPhoneNumberVerified: isEqual(hasLoggedInUserConfirmedPhoneNumber, 'True') || //hasLoggedInUserConfirmedPhoneNumber: global verification phone state for contactSSOName === loggedInUser.data.ssoUsername
125
+ isEqual(hasLoggedInUserConfirmedPhoneNumber, 'Deferred')
126
+ ? hasLoggedInUserConfirmedPhoneNumber
127
+ : 'False',
117
128
  });
118
129
  }
119
130
  else {
120
131
  yield updatePhone({
121
- phoneAreaCodePrefixLineNumber: getPhoneObj(loggedInUser.data.phone).phoneLine || '',
122
- phoneCountryCode: getPhoneObj(loggedInUser.data.phone).countryCode || '',
123
- suppliedPhoneNumberVerified: 'False',
132
+ phoneAreaCodePrefixLineNumber: getPhoneObj(loggedInUserContact.phone).phoneLine || '',
133
+ phoneCountryCode: getPhoneObj(loggedInUserContact.phone).countryCode || '',
134
+ suppliedPhoneNumberVerified: isEqual(hasLoggedInUserConfirmedPhoneNumber, 'True') || //hasLoggedInUserConfirmedPhoneNumber: global verification phone state for contactSSOName === loggedInUser.data.ssoUsername
135
+ isEqual(hasLoggedInUserConfirmedPhoneNumber, 'Deferred')
136
+ ? hasLoggedInUserConfirmedPhoneNumber
137
+ : 'False',
124
138
  });
125
139
  }
126
140
  }
@@ -212,6 +226,9 @@ function OwnerSelector(props) {
212
226
  setCaseState(caseDispatch, { isCaseOwnerUpdating: true });
213
227
  try {
214
228
  yield updateCaseDetails(caseDispatch, caseNumber, caseDetails);
229
+ setCaseDetails(caseDispatch, {
230
+ contactSSOName: newOwner.ssoUsername,
231
+ });
215
232
  const abortSignal = new AbortController().signal;
216
233
  yield setCaseOwner(caseDispatch, {
217
234
  ssoUsername: newOwner.ssoUsername,
@@ -221,9 +238,9 @@ function OwnerSelector(props) {
221
238
  }, '', abortSignal);
222
239
  setLocalOwnerChange(true);
223
240
  updateNotifyUsersList(newOwner);
241
+ ToastNotification.addSuccessMessage(t(`Owner has been successfully updated`));
224
242
  yield updateContactPhoneNumber(newOwner.ssoUsername);
225
243
  setCaseState(caseDispatch, { isCaseOwnerUpdating: false });
226
- ToastNotification.addSuccessMessage(t(`Owner has been successfully updated`));
227
244
  }
228
245
  catch (e) {
229
246
  setCaseState(caseDispatch, { isCaseOwnerUpdating: false });
@@ -269,6 +286,26 @@ function OwnerSelector(props) {
269
286
  users.length > 0 && setUsersWithGroupAccess(sortHydraContacts(users));
270
287
  }
271
288
  }, [selectedCaseGroupUsers, caseNumber]);
289
+ // to populate the phone number with the logged in user data
290
+ useEffect(() => {
291
+ if (caseDetailes.contactSSOName === loggedInUser.data.ssoUsername) {
292
+ if (loggedInUser.data.supportPhoneAreaCodePrefixLineNumber) {
293
+ setCaseDetails(caseDispatch, {
294
+ phoneAreaCodePrefixLineNumber: loggedInUser.data.supportPhoneAreaCodePrefixLineNumber,
295
+ phoneCountryCode: loggedInUser.data.supportPhoneCountryCode,
296
+ });
297
+ }
298
+ else {
299
+ const phoneLine = getPhoneObj(loggedInUser.data.phone).phoneLine || '';
300
+ const countryCode = getPhoneObj(loggedInUser.data.phone).countryCode;
301
+ setCaseDetails(caseDispatch, {
302
+ phoneAreaCodePrefixLineNumber: phoneLine,
303
+ phoneCountryCode: countryCode,
304
+ });
305
+ }
306
+ }
307
+ // eslint-disable-next-line react-hooks/exhaustive-deps
308
+ }, []);
272
309
  const showUsersWithSelectedGroupAccess = caseNumber &&
273
310
  (selectedCaseGroupUsers.isFetching ||
274
311
  (!selectedCaseGroupUsers.isFetching && (selectedCaseGroupUsers.data || []).length > 0));
@@ -1 +1 @@
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,qBAqN5C"}
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;AAyBlE,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,qBAiO5C"}
@@ -11,6 +11,7 @@ import { useCaseSelector } from '../../context/CaseContext';
11
11
  import { useCaseDetailsPageStateContext } from '../../context/CaseDetailsPageContext';
12
12
  import { PDFContext } from './PDFContainer';
13
13
  import CaseDetailsManagement from './Tabs/CaseDetails/CaseDetailsManagement';
14
+ import CaseHistory from './Tabs/CaseHistory/CaseHistory';
14
15
  const RelatedTasks = React.lazy(() => import(/* webpackChunkName: 'CaseBugzilla' */ './Tabs/RelatedTasks/RelatedTasks'));
15
16
  const CaseActionPlan = React.lazy(() => import(/* webpackChunkName: 'CaseActionPlan' */ './Tabs/CaseActionPlan/CaseActionPlan'));
16
17
  const CasePrivateNotes = React.lazy(() => import(/* webpackChunkName: 'CasePrivateNotes' */ './Tabs/CasePrivateNotes/CasePrivateNotes'));
@@ -45,6 +46,7 @@ export function CaseDetailsTabs(props) {
45
46
  const actionPlanTabRef = useRef(null);
46
47
  const escalationTabRef = useRef(null);
47
48
  const relatedTasksRef = useRef(null);
49
+ const caseHistoryTabRef = useRef(null);
48
50
  const tabsToRender = [];
49
51
  const handleTabClick = (event, tabIndex) => {
50
52
  setActiveTabKey(tabIndex);
@@ -102,6 +104,15 @@ export function CaseDetailsTabs(props) {
102
104
  routePath: 'escalation',
103
105
  component: (React.createElement(RMEEscalationList, { escalations: caseEscalations.data, caseNumber: caseNumber, caseStatus: status, accountNumber: loggedInUserRights.data.getAccountNumber(), isInternal: loggedInUserRights.data.isInternal() })),
104
106
  });
107
+ false && //Don't add this component to 'tabsToRender' for now, pending QA release
108
+ tabsToRender.push({
109
+ 'data-tracking-id': 'case-history-tab',
110
+ title: CaseDetailsTabsEnum.HISTORY,
111
+ key: 'history',
112
+ routePath: 'history',
113
+ ref: caseHistoryTabRef,
114
+ component: React.createElement(CaseHistory, { caseNumber: caseNumber }),
115
+ });
105
116
  const getActiveTabKey = () => {
106
117
  if (!activeTab)
107
118
  return activeTabKey;
@@ -1 +1 @@
1
- {"version":3,"file":"CaseContactPhoneNumber.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.tsx"],"names":[],"mappings":"AAQA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAgB/D,wBAAgB,sBAAsB,sBAoPrC"}
1
+ {"version":3,"file":"CaseContactPhoneNumber.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseContactPhoneNumber.tsx"],"names":[],"mappings":"AASA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAgB/D,wBAAgB,sBAAsB,sBAkTrC"}
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { contacts } from '@cee-eng/hydrajs';
11
11
  import { InputGroupText, ValidatedOptions } from '@patternfly/react-core';
12
12
  import CheckIcon from '@patternfly/react-icons/dist/js/icons/check-icon';
13
+ import PencilAltIcon from '@patternfly/react-icons/dist/js/icons/pencil-alt-icon';
13
14
  import TimesIcon from '@patternfly/react-icons/dist/js/icons/times-icon';
14
15
  import { getPhoneObj, PhoneInput, ToastNotification } from '@rh-support/components';
15
16
  import { GlobalMetadataStateContext, useCanEditCase } from '@rh-support/react-context';
@@ -21,7 +22,7 @@ import { PHONE_INSTRUCTION, PHONE_IS_NOT_VALID, PHONE_LINE_CANNOT_BE_EMPTY, PHON
21
22
  import { useCaseDispatch, useCaseSelector } from '../../../../context/CaseContext';
22
23
  import { useCaseUpdateErrorMessage } from '../../../../hooks/useCaseUpdateErrorMessage';
23
24
  import { PHONE_LIMIT } from '../../../../reducers/CaseConstNTypes';
24
- import { updateCaseDetails } from '../../../../reducers/CaseReducer';
25
+ import { setCaseState, updateCaseDetails } from '../../../../reducers/CaseReducer';
25
26
  import { ContactPhoneNumberPopOver } from '../../../CaseInformation/ContactPhoneNumberPopOver';
26
27
  import { trimAndReplacePlus } from '../../../shared/utils';
27
28
  import { PDFContext } from '../../PDFContainer';
@@ -38,6 +39,7 @@ export function CaseContactPhoneNumber() {
38
39
  const { globalMetadataState: { loggedInUser }, } = useContext(GlobalMetadataStateContext);
39
40
  const canEditCase = useCanEditCase();
40
41
  const [isCasePhoneUpdating, setCasePhoneUpdating] = useState(false);
42
+ const [isEditting, setIsEditting] = useState(false);
41
43
  const [localFullPhoneState, setLocalFullPhoneState] = useState(phoneCountryCode + ' ' + phoneAreaCodePrefixLineNumber);
42
44
  const [localCountryCodeState, setLocalCountryCodeState] = useState(phoneCountryCode);
43
45
  const [invalid, setInvalid] = useState(false);
@@ -58,6 +60,12 @@ export function CaseContactPhoneNumber() {
58
60
  return;
59
61
  setLocalCountryCodeState(countryCode);
60
62
  };
63
+ const regex = /[()\s-]/g; // to have only digits in phone
64
+ // To check if country code is given but phone number empty
65
+ const isPhoneNumberInvalid = !isEmpty(localFullPhoneState) &&
66
+ isEmpty(localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.replace(regex, '').replace(localCountryCodeState, ''));
67
+ const isPhoneLineEmpty = isEmpty(trimAndReplacePlus(localCountryCodeState)) &&
68
+ isEmpty(localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.replace(localCountryCodeState, ''));
61
69
  const onSave = () => __awaiter(this, void 0, void 0, function* () {
62
70
  setIsSavedClicked(true);
63
71
  if (isPhoneValueCannotBeSaved)
@@ -73,6 +81,7 @@ export function CaseContactPhoneNumber() {
73
81
  setIsSavedClicked(false);
74
82
  setCasePhoneUpdating(false);
75
83
  ToastNotification.addSuccessMessage(t(`Phone number has been successfully updated`));
84
+ setIsEditting(false);
76
85
  try {
77
86
  // update logged-in user contact info
78
87
  if (contactSSOName === loggedInUser.data.ssoUsername && !isEmpty(phoneLine) && !isEmpty(countryCode)) {
@@ -94,47 +103,59 @@ export function CaseContactPhoneNumber() {
94
103
  const onClear = () => __awaiter(this, void 0, void 0, function* () {
95
104
  setLocalFullPhoneState('');
96
105
  setLocalCountryCodeState('');
97
- setCasePhoneUpdating(true);
98
- try {
99
- yield updateCaseDetails(caseDispatch, caseNumber, {
100
- phoneCountryCode: '',
101
- phoneAreaCodePrefixLineNumber: '',
102
- clearPhoneNumber: true,
103
- suppliedPhoneNumberVerified: 'False',
104
- });
105
- setCasePhoneUpdating(false);
106
- ToastNotification.addSuccessMessage(t(`Phone number has been successfully updated`));
107
- }
108
- catch (e) {
109
- setCasePhoneUpdating(false);
110
- caseUpdateError.showError(e, t(`Phone number failed to update`));
111
- }
112
106
  });
113
107
  const maxLengthErrorMessage = t('Phone number cannot be more than {{limit}} digits.', {
114
108
  limit: PHONE_LIMIT,
115
109
  });
116
- const isPhoneNeedsReview = contactSSOName === loggedInUser.data.ssoUsername && suppliedPhoneNumberVerified === 'Deferred';
117
- // To check if country code is given but phone number empty
118
- const isPhoneLineEmpty = !isEmpty(localFullPhoneState) && isEmpty(localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.replace(localCountryCodeState, ''));
119
- const isPhoneNumberInvalid = isEmpty(localCountryCodeState) && !isEmpty(localFullPhoneState);
110
+ const isPhoneNeedsReview = !isEmpty(contactSSOName) &&
111
+ contactSSOName === loggedInUser.data.ssoUsername &&
112
+ suppliedPhoneNumberVerified === 'Deferred' &&
113
+ !isCaseOwnerUpdating &&
114
+ !isCasePhoneUpdating &&
115
+ !isEmpty(localFullPhoneState);
120
116
  const isPhoneNumberValid = (localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.length) > PHONE_LIMIT
121
117
  ? ValidatedOptions.error
122
118
  : isPhoneNeedsReview
123
119
  ? ValidatedOptions.warning
124
- : isSaveClicked && (isPhoneLineEmpty || isPhoneNumberInvalid)
120
+ : isSaveClicked &&
121
+ (isPhoneLineEmpty || isPhoneNumberInvalid || isEmpty(trimAndReplacePlus(localCountryCodeState)))
125
122
  ? ValidatedOptions.error
126
123
  : invalid
127
124
  ? ValidatedOptions.error
128
125
  : ValidatedOptions.default;
129
- const isPhoneValueCannotBeSaved = isPhoneLineEmpty || isPhoneNumberInvalid || localFullPhoneState.trim() === localCountryCodeState.trim();
130
- // should be removed when old phone field is removed by CCM team
126
+ const isPhoneValueCannotBeSaved = isPhoneLineEmpty ||
127
+ isPhoneNumberInvalid ||
128
+ isEmpty(trimAndReplacePlus(localCountryCodeState)) ||
129
+ trimAndReplacePlus(localFullPhoneState) === trimAndReplacePlus(localCountryCodeState);
131
130
  useEffect(() => {
131
+ if (isEqual(localFullPhoneState.trim(), '+')) {
132
+ setLocalFullPhoneState('');
133
+ }
134
+ if (isEqual(localCountryCodeState.trim(), '+')) {
135
+ setLocalCountryCodeState('');
136
+ }
137
+ // eslint-disable-next-line react-hooks/exhaustive-deps
138
+ }, [localFullPhoneState]);
139
+ const updatePhone = () => __awaiter(this, void 0, void 0, function* () {
132
140
  var _a, _b;
133
141
  if (isEmpty(phoneCountryCode) && isEmpty(phoneAreaCodePrefixLineNumber) && !isEmpty(phone)) {
134
142
  const oldPhoneline = ((_a = getPhoneObj(phone)) === null || _a === void 0 ? void 0 : _a.phoneLine) || '';
135
143
  const oldCountryCode = ((_b = getPhoneObj(phone)) === null || _b === void 0 ? void 0 : _b.countryCode) || '';
136
144
  if (!isEmpty(oldPhoneline.trim()) && !isEmpty(trimAndReplacePlus(oldCountryCode))) {
137
145
  setLocalFullPhoneState(oldCountryCode + ' ' + oldPhoneline);
146
+ setLocalCountryCodeState(oldCountryCode);
147
+ setCasePhoneUpdating(true);
148
+ try {
149
+ yield updateCaseDetails(caseDispatch, caseNumber, {
150
+ phoneCountryCode: oldCountryCode,
151
+ phoneAreaCodePrefixLineNumber: oldPhoneline,
152
+ });
153
+ setCasePhoneUpdating(false);
154
+ }
155
+ catch (e) {
156
+ setCasePhoneUpdating(false);
157
+ caseUpdateError.showError(e, t(`Phone number failed to update`));
158
+ }
138
159
  }
139
160
  else {
140
161
  setIsShowOldPhone(true);
@@ -144,20 +165,40 @@ export function CaseContactPhoneNumber() {
144
165
  setLocalFullPhoneState((phoneCountryCode + ' ' + phoneAreaCodePrefixLineNumber).trim());
145
166
  setIsShowOldPhone(false);
146
167
  }
168
+ });
169
+ // should be removed when old phone field is removed by CCM team
170
+ useEffect(() => {
171
+ updatePhone();
172
+ // eslint-disable-next-line react-hooks/exhaustive-deps
173
+ }, [phone, phoneAreaCodePrefixLineNumber, phoneCountryCode]);
174
+ useEffect(() => {
175
+ if (contactSSOName === loggedInUser.data.ssoUsername) {
176
+ // edge case: when loggedInUser === contactSSOName while opening a case confirms or deffers the phone
177
+ // we need to save the verification state globallly so that we don't show the phone review banner again
178
+ // to the user where he changes it to another owner and then again assigns himself as the case owner
179
+ setCaseState(caseDispatch, {
180
+ hasLoggedInUserConfirmedPhoneNumber: suppliedPhoneNumberVerified,
181
+ });
182
+ }
147
183
  // eslint-disable-next-line react-hooks/exhaustive-deps
148
- }, []);
184
+ }, [suppliedPhoneNumberVerified]);
149
185
  return (React.createElement("div", { className: "form-group pf-v5-u-pb-md", style: { minWidth: '200px' } },
150
186
  React.createElement("h3", { className: `subheading subheading-sm ${isExportingPDF ? 'expand-input' : ''}` },
151
187
  React.createElement(Trans, null, "Case owner's phone number"),
188
+ React.createElement("span", { className: `form-required ${isExportingPDF ? 'hide-in-pdf' : ''}`, "aria-hidden": true }, "*"),
152
189
  !isExportingPDF ? ContactPhoneNumberPopOver() : ''),
153
190
  React.createElement(InputGroupText, null,
154
- React.createElement(PhoneInput, { phoneValue: localFullPhoneState, onPhoneValueChange: onPhoneChange, onCountryCodeChange: onCountryCodeChange, validations: isPhoneNumberValid, isDisabled: isCasePhoneUpdating || isCaseOwnerUpdating, isLoading: isCasePhoneUpdating, "data-tracking-id": "case-details-page-supplied-phone", invalid: invalid, setInvalid: setInvalid }),
155
- React.createElement("button", { className: "btn btn-app btn-link pf-v5-u-ml-sm", type: "button", "data-tracking-id": "case-details-page-supplied-phone-save", onClick: () => onSave(), "aria-label": "Save", disabled: (localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.length) > PHONE_LIMIT ||
156
- localFullPhoneState === phoneCountryCode + ' ' + phoneAreaCodePrefixLineNumber ||
157
- (isSaveClicked && isPhoneValueCannotBeSaved), style: { display: isExportingPDF ? 'none' : '' } },
158
- React.createElement(CheckIcon, null)),
159
- React.createElement("button", { className: "btn btn-app btn-link", type: "button", onClick: onClear, "data-tracking-id": "case-details-page-supplied-phone-cancel", style: { display: isExportingPDF ? 'none' : '' }, disabled: isEmpty(localFullPhoneState), "aria-label": "Clear" },
160
- React.createElement(TimesIcon, { color: "#6A6E73" }))),
191
+ React.createElement(PhoneInput, { phoneValue: localFullPhoneState, onPhoneValueChange: onPhoneChange, onCountryCodeChange: onCountryCodeChange, validations: isPhoneNumberValid, isDisabled: isCasePhoneUpdating || isCaseOwnerUpdating || !isEditting, isLoading: isCasePhoneUpdating || isCaseOwnerUpdating, "data-tracking-id": "case-details-page-supplied-phone", invalid: invalid, setInvalid: setInvalid }),
192
+ isEditting ? (React.createElement(React.Fragment, null,
193
+ React.createElement("button", { className: "btn btn-app btn-link pf-v5-u-ml-sm", type: "button", "data-tracking-id": "case-details-page-supplied-phone-save", onClick: () => onSave(), "aria-label": "Save", disabled: (isSaveClicked && isPhoneValueCannotBeSaved) ||
194
+ (localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.length) > PHONE_LIMIT ||
195
+ localFullPhoneState === phoneCountryCode + ' ' + phoneAreaCodePrefixLineNumber ||
196
+ isCaseOwnerUpdating ||
197
+ isCasePhoneUpdating, style: { display: isExportingPDF ? 'none' : '' } },
198
+ React.createElement(CheckIcon, null)),
199
+ React.createElement("button", { className: "btn btn-app btn-link", type: "button", onClick: onClear, "data-tracking-id": "case-details-page-supplied-phone-cancel", style: { display: isExportingPDF ? 'none' : '' }, disabled: isEmpty(localFullPhoneState) || isCaseOwnerUpdating || isCasePhoneUpdating, "aria-label": "Clear" },
200
+ React.createElement(TimesIcon, { color: "#6A6E73" })))) : (React.createElement("button", { className: "btn btn-app btn-link", type: "button", onClick: () => setIsEditting(true), "data-tracking-id": "case-details-page-supplied-phone-edit", style: { display: isExportingPDF ? 'none' : '' }, "aria-label": "Edit" },
201
+ React.createElement(PencilAltIcon, null)))),
161
202
  !invalid &&
162
203
  (localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.length) < PHONE_LIMIT &&
163
204
  !(isSaveClicked && isPhoneValueCannotBeSaved) &&
@@ -166,9 +207,11 @@ export function CaseContactPhoneNumber() {
166
207
  invalid && (React.createElement("p", { className: "form-instructions form-invalid" },
167
208
  React.createElement(Trans, null, PHONE_NO_CHAR_ERROR))),
168
209
  (localFullPhoneState === null || localFullPhoneState === void 0 ? void 0 : localFullPhoneState.length) > PHONE_LIMIT && (React.createElement("p", { className: "form-instructions form-invalid" }, maxLengthErrorMessage)),
169
- isSaveClicked && (isPhoneLineEmpty || localFullPhoneState.trim() === localCountryCodeState.trim()) && (React.createElement("p", { className: "form-instructions form-invalid" },
170
- React.createElement(Trans, null, PHONE_LINE_CANNOT_BE_EMPTY))),
210
+ isSaveClicked && isPhoneLineEmpty && (React.createElement("p", { className: "form-instructions form-invalid" },
211
+ React.createElement(Trans, null, PHONE_INSTRUCTION))),
171
212
  isSaveClicked && isPhoneNumberInvalid && (React.createElement("p", { className: "form-instructions form-invalid" },
213
+ React.createElement(Trans, null, PHONE_LINE_CANNOT_BE_EMPTY))),
214
+ isSaveClicked && isEmpty(trimAndReplacePlus(localCountryCodeState)) && !isPhoneLineEmpty && (React.createElement("p", { className: "form-instructions form-invalid" },
172
215
  React.createElement(Trans, null, PHONE_IS_NOT_VALID))),
173
216
  isShowOldPhone && (React.createElement("p", { className: "form-instructions form-invalid" },
174
217
  React.createElement(Trans, null,
@@ -1 +1 @@
1
- {"version":3,"file":"CasePhoneNumberConfirmAlert.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.tsx"],"names":[],"mappings":"AAMA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAUpD,UAAU,MAAM;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,qBAoGxD"}
1
+ {"version":3,"file":"CasePhoneNumberConfirmAlert.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberConfirmAlert.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAUpD,UAAU,MAAM;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,qBAuGxD"}
@@ -11,6 +11,7 @@ import { Alert, AlertVariant, Button, ButtonVariant } from '@patternfly/react-co
11
11
  import { ToastNotification } from '@rh-support/components';
12
12
  import { GlobalMetadataStateContext } from '@rh-support/react-context';
13
13
  import { scrollIntoView } from '@rh-support/utils';
14
+ import isEmpty from 'lodash/isEmpty';
14
15
  import isEqual from 'lodash/isEqual';
15
16
  import React, { useContext, useState } from 'react';
16
17
  import { Trans, useTranslation } from 'react-i18next';
@@ -22,10 +23,11 @@ import { PDFContext } from '../../PDFContainer';
22
23
  export function CaseContactPhoneNumberAlert(props) {
23
24
  const { globalMetadataState: { loggedInUser }, } = useContext(GlobalMetadataStateContext);
24
25
  const [isCaseUpdating, setCasUpdating] = useState(false);
25
- const { caseNumber, suppliedPhoneNumberVerified, contactSSOName, severity } = useCaseSelector((state) => ({
26
+ const { caseNumber, suppliedPhoneNumberVerified, contactSSOName, isCaseOwnerUpdating, severity } = useCaseSelector((state) => ({
26
27
  caseNumber: state.caseDetails.caseNumber,
27
28
  suppliedPhoneNumberVerified: state.caseDetails.suppliedPhoneNumberVerified,
28
29
  contactSSOName: state.caseDetails.contactSSOName,
30
+ isCaseOwnerUpdating: state.isCaseOwnerUpdating,
29
31
  severity: state.caseDetails.severity,
30
32
  }), isEqual);
31
33
  const { t } = useTranslation();
@@ -47,8 +49,10 @@ export function CaseContactPhoneNumberAlert(props) {
47
49
  const goToPhoneField = () => {
48
50
  scrollIntoView(props.tabRef);
49
51
  };
50
- const isPhoneNeedsReview = contactSSOName === loggedInUser.data.ssoUsername &&
52
+ const isPhoneNeedsReview = !isEmpty(contactSSOName) &&
53
+ contactSSOName === loggedInUser.data.ssoUsername &&
51
54
  suppliedPhoneNumberVerified === 'Deferred' &&
55
+ !isCaseOwnerUpdating &&
52
56
  severity !== "1 (Urgent)" /* SeverityLevelsInternal.SEV_1 */; // we show another alert when sev is 1
53
57
  const NEW_OWNER_MSG = 'You are the new owner for this case. Is the new phone number correct?';
54
58
  if (!isPhoneNeedsReview)
@@ -1 +1 @@
1
- {"version":3,"file":"CasePhoneNumberSev1ConfirmAlert.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberSev1ConfirmAlert.tsx"],"names":[],"mappings":"AAMA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAUpD,UAAU,MAAM;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AAMD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,MAAM,qBAoG5D"}
1
+ {"version":3,"file":"CasePhoneNumberSev1ConfirmAlert.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CasePhoneNumberSev1ConfirmAlert.tsx"],"names":[],"mappings":"AAOA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAUpD,UAAU,MAAM;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AAMD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,MAAM,qBAuG5D"}
@@ -11,6 +11,7 @@ import { Alert, AlertVariant, Button, ButtonVariant } from '@patternfly/react-co
11
11
  import { ToastNotification } from '@rh-support/components';
12
12
  import { GlobalMetadataStateContext } from '@rh-support/react-context';
13
13
  import { scrollIntoView } from '@rh-support/utils';
14
+ import isEmpty from 'lodash/isEmpty';
14
15
  import isEqual from 'lodash/isEqual';
15
16
  import React, { useContext, useState } from 'react';
16
17
  import { Trans, useTranslation } from 'react-i18next';
@@ -26,11 +27,12 @@ On case detail page when case owner changes the sevirity to sev1, this alert wil
26
27
  export function CasePhoneNumberSev1ConfirmAlert(props) {
27
28
  const { globalMetadataState: { loggedInUser }, } = useContext(GlobalMetadataStateContext);
28
29
  const [isCaseUpdating, setCasUpdating] = useState(false);
29
- const { caseNumber, suppliedPhoneNumberVerified, contactSSOName, severity } = useCaseSelector((state) => ({
30
+ const { caseNumber, suppliedPhoneNumberVerified, contactSSOName, severity, isCaseOwnerUpdating } = useCaseSelector((state) => ({
30
31
  caseNumber: state.caseDetails.caseNumber,
31
32
  suppliedPhoneNumberVerified: state.caseDetails.suppliedPhoneNumberVerified,
32
33
  contactSSOName: state.caseDetails.contactSSOName,
33
34
  severity: state.caseDetails.severity,
35
+ isCaseOwnerUpdating: state.isCaseOwnerUpdating,
34
36
  }), isEqual);
35
37
  const { t } = useTranslation();
36
38
  const caseDispatch = useCaseDispatch();
@@ -51,9 +53,11 @@ export function CasePhoneNumberSev1ConfirmAlert(props) {
51
53
  const goToPhoneField = () => {
52
54
  scrollIntoView(props.tabRef);
53
55
  };
54
- const isPhoneNeedsConfirm = contactSSOName === loggedInUser.data.ssoUsername &&
56
+ const isPhoneNeedsConfirm = !isEmpty(contactSSOName) &&
57
+ contactSSOName === loggedInUser.data.ssoUsername &&
55
58
  severity === "1 (Urgent)" /* SeverityLevelsInternal.SEV_1 */ &&
56
- suppliedPhoneNumberVerified !== 'True';
59
+ suppliedPhoneNumberVerified !== 'True' &&
60
+ !isCaseOwnerUpdating;
57
61
  const SEV1_MSG = 'This case severity is urgent. Please confirm the phone number we have on file is correct.';
58
62
  if (!isPhoneNeedsConfirm)
59
63
  return React.createElement(React.Fragment, null);
@@ -17,7 +17,7 @@ const CaseExternalTrackerUpdate = React.forwardRef((props, ref) => {
17
17
  const canSeePrivateComments = ability.can(resourceActions.PATCH, resources.CASE_COMMENTS, CaseDiscussionFields.VIEW_PRIVATE_COMMENT);
18
18
  const sanitize = (markdown) => {
19
19
  const htmlString = markdownToHTML(markdown, { openLinksInNewTab: true });
20
- return { __html: DOMPurify.sanitize(htmlString) };
20
+ return { __html: DOMPurify.sanitize(htmlString, { FORBID_TAGS: ['style'] }) };
21
21
  };
22
22
  const onJumpToComment = (externalTrackerId) => () => props.showJumpToComment && props.onJumpToComment && props.onJumpToComment(externalTrackerId);
23
23
  // To check and set if a comment is private or not
@@ -1,6 +1,8 @@
1
+ import './CaseHistory.css';
1
2
  import React from 'react';
2
3
  interface IProps {
4
+ caseNumber: string;
3
5
  }
4
- export default function CaseHistory(props: IProps): React.JSX.Element;
5
- export {};
6
+ declare const CaseHistory: (props: IProps) => React.JSX.Element;
7
+ export default CaseHistory;
6
8
  //# sourceMappingURL=CaseHistory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CaseHistory.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseHistory/CaseHistory.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,UAAU,MAAM;CAAG;AAEnB,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAK,EAAE,MAAM,qBAEhD"}
1
+ {"version":3,"file":"CaseHistory.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseHistory/CaseHistory.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC;AAE3B,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,QAAA,MAAM,WAAW,UAAW,MAAM,sBAMjC,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -1,4 +1,8 @@
1
+ import './CaseHistory.css';
1
2
  import React from 'react';
2
- export default function CaseHistory(props) {
3
- return React.createElement(React.Fragment, null, "CaseHistory");
4
- }
3
+ import Timeline from './Timeline';
4
+ const CaseHistory = (props) => {
5
+ return (React.createElement("div", null,
6
+ React.createElement(Timeline, { caseNumber: props.caseNumber })));
7
+ };
8
+ export default CaseHistory;