@rh-support/troubleshoot 2.6.334 → 2.6.335

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 (51) hide show
  1. package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.js +1 -1
  2. package/lib/esm/components/CaseEditView/CaseOverview/CaseStatus.js +2 -2
  3. package/lib/esm/components/CaseEditView/CaseOverview/index.d.ts.map +1 -1
  4. package/lib/esm/components/CaseEditView/CaseOverview/index.js +13 -8
  5. package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutions.d.ts.map +1 -1
  6. package/lib/esm/components/CaseEditView/CaseSolutions/CaseSolutions.js +1 -1
  7. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.d.ts.map +1 -1
  8. package/lib/esm/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.js +106 -71
  9. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.d.ts +1 -0
  10. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.d.ts.map +1 -1
  11. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.js +3 -1
  12. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.d.ts.map +1 -1
  13. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.js +11 -4
  14. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.d.ts +4 -2
  15. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.d.ts.map +1 -1
  16. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.js +11 -4
  17. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts +3 -0
  18. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts.map +1 -1
  19. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.js +42 -13
  20. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/VerifyCaseStatusModal/VerifyCaseStatusModal.d.ts.map +1 -1
  21. package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/VerifyCaseStatusModal/VerifyCaseStatusModal.js +1 -1
  22. package/lib/esm/components/CaseManagement/NoClusterIDReasonSelector.d.ts +2 -1
  23. package/lib/esm/components/CaseManagement/NoClusterIDReasonSelector.d.ts.map +1 -1
  24. package/lib/esm/components/CaseManagement/NoClusterIDReasonSelector.js +19 -3
  25. package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.d.ts.map +1 -1
  26. package/lib/esm/components/CaseManagement/OpenshiftDropdownV4.js +13 -14
  27. package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.d.ts.map +1 -1
  28. package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.js +7 -3
  29. package/lib/esm/constants/caseDetailsConstants.d.ts +5 -0
  30. package/lib/esm/constants/caseDetailsConstants.d.ts.map +1 -1
  31. package/lib/esm/constants/caseDetailsConstants.js +5 -0
  32. package/lib/esm/hooks/useCaseComments/index.d.ts +1 -1
  33. package/lib/esm/hooks/useCaseComments/index.d.ts.map +1 -1
  34. package/lib/esm/hooks/useCaseComments/index.js +1 -1
  35. package/lib/esm/hooks/useCaseComments/useCreateCaseComment.d.ts.map +1 -1
  36. package/lib/esm/hooks/useCaseComments/useCreateCaseComment.js +1 -2
  37. package/lib/esm/hooks/useCaseUpdateErrorMessage.d.ts +1 -1
  38. package/lib/esm/hooks/useCaseUpdateErrorMessage.d.ts.map +1 -1
  39. package/lib/esm/hooks/useCaseUpdateErrorMessage.js +21 -11
  40. package/lib/esm/reducers/CaseConstNTypes.d.ts +1 -0
  41. package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
  42. package/lib/esm/reducers/CaseDiscussionTabReducer.d.ts +5 -0
  43. package/lib/esm/reducers/CaseDiscussionTabReducer.d.ts.map +1 -1
  44. package/lib/esm/reducers/CaseDiscussionTabReducer.js +15 -0
  45. package/lib/esm/reducers/CaseReducer.d.ts.map +1 -1
  46. package/lib/esm/reducers/CaseReducer.js +9 -6
  47. package/lib/esm/scss/_main.scss +9 -0
  48. package/package.json +6 -6
  49. package/lib/esm/hooks/useCaseComments/caseCommentMutation.d.ts +0 -4
  50. package/lib/esm/hooks/useCaseComments/caseCommentMutation.d.ts.map +0 -1
  51. package/lib/esm/hooks/useCaseComments/caseCommentMutation.js +0 -12
@@ -101,7 +101,7 @@ export function RequestEscalationModal(props) {
101
101
  Subject: formState.subject,
102
102
  Description: serializedDescription,
103
103
  Status: 'In Progress',
104
- Origin: 'Portal ACE',
104
+ Origin: 'Portal RME',
105
105
  Priority: props.severity || '3 (Medium)',
106
106
  Type: 'RME',
107
107
  RecordTypeId: '012Ek00000JUtx5IAD',
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { SingleSelectDropdown, ValueChangedIcon } from '@rh-support/components';
11
- import { mapSfdcStatusToPortalStatus, PORTAL_DISPLAY_STATUSES } from '@rh-support/utils';
11
+ import { mapSfdcStatusToPortalStatus, PORTAL_USER_SELECTABLE_STATUSES } from '@rh-support/utils';
12
12
  import isEmpty from 'lodash/isEmpty';
13
13
  import map from 'lodash/map';
14
14
  import React, { useContext, useMemo, useState } from 'react';
@@ -39,7 +39,7 @@ function CaseStatus(props) {
39
39
  setLocalStatusChange(true);
40
40
  validateCaseStatus(option);
41
41
  });
42
- const getDropdownOptions = map(PORTAL_DISPLAY_STATUSES, (option) => ({
42
+ const getDropdownOptions = map(PORTAL_USER_SELECTABLE_STATUSES, (option) => ({
43
43
  label: option,
44
44
  value: option,
45
45
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseEditView/CaseOverview/index.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAkD,MAAM,OAAO,CAAC;AA4BvE,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,qBAkhBjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseEditView/CaseOverview/index.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAkD,MAAM,OAAO,CAAC;AA4BvE,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,qBA4hBjD"}
@@ -156,7 +156,7 @@ export default function CaseOverview(props) {
156
156
  caseUpdateError.showError(e, t('Severity failed to update'));
157
157
  }
158
158
  });
159
- const updateStatusState = (statusVal_1, reopenedAt_1, reopenedBySSOName_1, reopenedReason_1, reopenedReasonOther_1, ...args_1) => __awaiter(this, [statusVal_1, reopenedAt_1, reopenedBySSOName_1, reopenedReason_1, reopenedReasonOther_1, ...args_1], void 0, function* (statusVal, reopenedAt, reopenedBySSOName, reopenedReason, reopenedReasonOther, onStatusUpdate = null) {
159
+ const updateStatusState = (statusVal, reopenedAt, reopenedBySSOName, reopenedReason, reopenedReasonOther, onStatusUpdate) => __awaiter(this, void 0, void 0, function* () {
160
160
  setStatusUpdating(caseOverviewDispatch, true);
161
161
  let updateStatusObj = {
162
162
  status: statusVal,
@@ -170,10 +170,12 @@ export default function CaseOverview(props) {
170
170
  setStatusUpdating(caseOverviewDispatch, false);
171
171
  onStatusUpdate && (yield onStatusUpdate());
172
172
  ToastNotification.addSuccessMessage(t('Status has been successfully updated'));
173
+ return true;
173
174
  }
174
175
  catch (e) {
175
176
  setStatusUpdating(caseOverviewDispatch, false);
176
- caseUpdateError.showError(e, t('Status failed to update'));
177
+ caseUpdateError.showError(e, t('Status failed to update, try refreshing the page. Please contact us if the problem persists.'));
178
+ return false;
177
179
  }
178
180
  });
179
181
  const onStatusChange = (newPortalStatus) => __awaiter(this, void 0, void 0, function* () {
@@ -238,6 +240,7 @@ export default function CaseOverview(props) {
238
240
  };
239
241
  const portalStatus = mapSfdcStatusToPortalStatus(status);
240
242
  const isCaseInOpenState = portalStatus !== 'Closed' && portalStatus !== 'Archived';
243
+ const isCaseArchived = portalStatus === 'Archived';
241
244
  // To switch from old case type to new support type
242
245
  const newCaseTypesArray = toNewCaseTypeMapper(allCaseTypes.data).sort();
243
246
  return (React.createElement(React.Fragment, null,
@@ -262,13 +265,13 @@ export default function CaseOverview(props) {
262
265
  props.caseNumber),
263
266
  React.createElement("div", null,
264
267
  exportPDFButton(props.caseNumber),
265
- React.createElement(Button, Object.assign({ className: `pf-v6-u-ml-md ${isExportingPDF ? 'hide-in-pdf' : ''}`, isDisabled: !canManageCase }, ((showCloseCaseModal || showReOpenCaseModal) &&
268
+ !isCaseArchived && (React.createElement(Button, Object.assign({ className: `pf-v6-u-ml-md ${isExportingPDF ? 'hide-in-pdf' : ''}`, isDisabled: !canManageCase }, ((showCloseCaseModal || showReOpenCaseModal) &&
266
269
  isCaseUpdating && {
267
270
  isLoading: true,
268
271
  }), { onClick: () => (isCaseInOpenState ? onCaseClose() : onCaseReopen()), variant: isCaseInOpenState ? ButtonVariant.secondary : ButtonVariant.tertiary, "data-tracking-id": isCaseInOpenState
269
272
  ? 'case-close-btn-case-details-overview'
270
273
  : 'case-reopen-btn-case-details-overview' }),
271
- React.createElement(Trans, null, isCaseInOpenState ? 'Close case' : 'Reopen case')))),
274
+ React.createElement(Trans, null, isCaseInOpenState ? 'Close case' : 'Reopen case'))))),
272
275
  React.createElement("div", { className: `case-details-header-secondary push-bottom-narrow pf-v6-u-mb-sm ${isExportingPDF && !viewAsCustomer ? 'hide-in-pdf' : ''}` },
273
276
  React.createElement("span", { className: `case-support-level ${isExportingPDF ? 'hide-in-pdf' : ''}` }, computeSupportLink())),
274
277
  React.createElement("div", { className: "case-details-summary push-bottom-narrow" },
@@ -308,7 +311,7 @@ export default function CaseOverview(props) {
308
311
  React.createElement("div", { className: "case-overview-secondary card card-md card-light push-bottom" },
309
312
  React.createElement("div", { className: "pf-v6-l-grid pf-m-gutter pf-m-all-4-col-on-lg" },
310
313
  React.createElement("div", { className: "form-wrapper" },
311
- React.createElement(CaseStatus, { selectedStatus: status, onStatusChange: onStatusChange, isDisabled: !canManageCase || allCaseStatuses.isFetching, isFetching: caseOverviewState.caseStatusUpdating && isCaseUpdating, hasError: allCaseStatuses.isError })),
314
+ React.createElement(CaseStatus, { selectedStatus: status, onStatusChange: onStatusChange, isDisabled: !canManageCase || allCaseStatuses.isFetching || isCaseArchived, isFetching: caseOverviewState.caseStatusUpdating && isCaseUpdating, hasError: allCaseStatuses.isError })),
312
315
  React.createElement("div", { className: "form-wrapper" },
313
316
  React.createElement(CaseType, { selectedType: switchedCaseType, onTypeChange: onTypeChange, isDisabled: !canManageCase || allCaseTypes.isFetching || isCaseUpdating, allTypes: newCaseTypesArray, isFetching: caseOverviewState.caseTypeUpdating && isCaseUpdating, hasError: allCaseTypes.isError })),
314
317
  React.createElement("div", { className: "form-wrapper" },
@@ -316,10 +319,12 @@ export default function CaseOverview(props) {
316
319
  React.createElement(ExpandableSection, { className: "case-details-main", toggleText: t('Case information'), isExpanded: isDetailsExpanded, onToggle: onToggleDetails },
317
320
  React.createElement(CaseInformation, null))),
318
321
  showCloseCaseModal && (React.createElement(CloseCaseModal, { onConfirm: (commentBody) => __awaiter(this, void 0, void 0, function* () {
319
- yield updateStatusState(CaseStatusEnum.CLOSED);
320
- yield postCommentAfterStatusUpdate(commentBody);
322
+ const success = yield updateStatusState(CaseStatusEnum.CLOSED);
323
+ if (success) {
324
+ yield postCommentAfterStatusUpdate(commentBody);
325
+ dtmTrackEventCaseStepEncountered('close', caseNumber, product, version);
326
+ }
321
327
  setShowCaseCloseModal(false);
322
- dtmTrackEventCaseStepEncountered('close', caseNumber, product, version);
323
328
  }), isUpdating: (caseOverviewState.caseStatusUpdating && isCaseUpdating) || isPostingComment, onClose: () => {
324
329
  setShowCaseCloseModal(false);
325
330
  }, caseNumber: caseNumber })),
@@ -1 +1 @@
1
- {"version":3,"file":"CaseSolutions.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseEditView/CaseSolutions/CaseSolutions.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAwF3E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,EAAE,OAAO,CAAC;CACnC;AAUD,eAAO,MAAM,aAAa,+EAmhBxB,CAAC"}
1
+ {"version":3,"file":"CaseSolutions.d.ts","sourceRoot":"","sources":["../../../../../src/components/CaseEditView/CaseSolutions/CaseSolutions.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAwF3E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB,EAAE,OAAO,CAAC;CACnC;AAUD,eAAO,MAAM,aAAa,+EAshBxB,CAAC"}
@@ -161,7 +161,7 @@ export const CaseSolutions = forwardRef((props, ref) => {
161
161
  setIsCloseCaseModalOpen(false);
162
162
  }
163
163
  catch (err) {
164
- caseUpdateError.showError(err, t('Status failed to update'));
164
+ caseUpdateError.showError(err, t('Status failed to update, try refreshing the page. Please contact us if the problem persists.'));
165
165
  }
166
166
  finally {
167
167
  setIsCaseCloseLoading(false);
@@ -1 +1 @@
1
- {"version":3,"file":"CaseOpenshiftClusterId.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.tsx"],"names":[],"mappings":"AAQA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAqB/D,wBAAgB,sBAAsB,sBAyVrC"}
1
+ {"version":3,"file":"CaseOpenshiftClusterId.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDetails/CaseOpenshiftClusterId/CaseOpenshiftClusterId.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAqBxE,wBAAgB,sBAAsB,sBA+YrC"}
@@ -10,11 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { useApolloClient } from '@apollo/client/react';
11
11
  import { LoadingIndicator, ToastNotification, usePrevious } from '@rh-support/components';
12
12
  import { GlobalMetadataStateContext } from '@rh-support/react-context';
13
- import { extractNoClusterIdFieldsFromDescription, getVersion } from '@rh-support/utils';
14
- import debounce from 'lodash/debounce';
13
+ import { extractNoClusterIdFieldsFromAdditionalCaseInformation, getVersion, hasNoClusterIdFieldsInAdditionalCaseInformation, } from '@rh-support/utils';
15
14
  import isEmpty from 'lodash/isEmpty';
16
15
  import isEqual from 'lodash/isEqual';
17
- import React, { useContext, useEffect, useState } from 'react';
16
+ import React, { useContext, useEffect, useMemo, useState } from 'react';
18
17
  import { useTranslation } from 'react-i18next';
19
18
  import { useCaseDispatch, useCaseSelector } from '../../../../../context/CaseContext';
20
19
  import { useCaseUpdateErrorMessage } from '../../../../../hooks/useCaseUpdateErrorMessage';
@@ -27,7 +26,7 @@ import { PDFContext } from '../../../PDFContainer';
27
26
  export function CaseOpenshiftClusterId() {
28
27
  const caseUpdateError = useCaseUpdateErrorMessage();
29
28
  const apolloClient = useApolloClient();
30
- const { openshiftClusterID, product, version, caseNumber, caseId, openshiftClusterVersion, noClusterIdReason, noClusterIdReasonExplanation, selectedAccountDetails, description, isFetchingCaseDetails, } = useCaseSelector((state) => ({
29
+ const { openshiftClusterID, product, version, caseNumber, caseId, openshiftClusterVersion, noClusterIdReason, noClusterIdReasonExplanation, selectedAccountDetails, description, additionalCaseInformation, isFetchingCaseDetails, } = useCaseSelector((state) => ({
31
30
  openshiftClusterID: state.caseDetails.openshiftClusterID,
32
31
  product: state.caseDetails.product,
33
32
  version: state.caseDetails.version,
@@ -38,6 +37,7 @@ export function CaseOpenshiftClusterId() {
38
37
  noClusterIdReasonExplanation: state.caseDetails.noClusterIdReasonExplanation,
39
38
  selectedAccountDetails: state.selectedAccountDetails,
40
39
  description: state.caseDetails.description,
40
+ additionalCaseInformation: state.caseDetails.additionalCaseInformation,
41
41
  isFetchingCaseDetails: state.isFetchingCaseDetails,
42
42
  }), isEqual);
43
43
  const caseDispatch = useCaseDispatch();
@@ -58,6 +58,47 @@ export function CaseOpenshiftClusterId() {
58
58
  const previousProduct = usePrevious(product);
59
59
  const { t } = useTranslation();
60
60
  const { isExportingPDF } = useContext(PDFContext);
61
+ const additionalCaseNoClusterFields = useMemo(() => extractNoClusterIdFieldsFromAdditionalCaseInformation(additionalCaseInformation), [additionalCaseInformation]);
62
+ const resolvedNoClusterFields = useMemo(() => ({
63
+ reason: noClusterIdReason || additionalCaseNoClusterFields.noClusterIdReason,
64
+ explanation: noClusterIdReasonExplanation || additionalCaseNoClusterFields.noClusterIdReasonExplanation,
65
+ }), [noClusterIdReason, noClusterIdReasonExplanation, additionalCaseNoClusterFields]);
66
+ const hasNoClusterIdSelection = useMemo(() => {
67
+ const { reason, explanation } = resolvedNoClusterFields;
68
+ if (reason) {
69
+ return true;
70
+ }
71
+ return explanation !== '' && explanation !== 'v3-cluster';
72
+ }, [resolvedNoClusterFields]);
73
+ const clusterDropdownId = useMemo(() => {
74
+ if (!isEmpty(localOpenshiftClusterIDState)) {
75
+ return localOpenshiftClusterIDState;
76
+ }
77
+ if (!isEmpty(selectedReason)) {
78
+ return selectedReason;
79
+ }
80
+ if (!isEmpty(openshiftClusterID)) {
81
+ return openshiftClusterID;
82
+ }
83
+ const { reason, explanation } = resolvedNoClusterFields;
84
+ if (reason === 'Other' && explanation === 'v3-cluster') {
85
+ return 'v3-cluster';
86
+ }
87
+ if (hasNoClusterIdSelection) {
88
+ return 'dont-have-id';
89
+ }
90
+ return '';
91
+ }, [
92
+ localOpenshiftClusterIDState,
93
+ selectedReason,
94
+ openshiftClusterID,
95
+ resolvedNoClusterFields,
96
+ hasNoClusterIdSelection,
97
+ ]);
98
+ const resolvedNoClusterIdReason = resolvedNoClusterFields.reason;
99
+ const resolvedNoClusterIdReasonExplanation = resolvedNoClusterFields.explanation;
100
+ const shouldShowNoClusterReasonSelector = resolvedNoClusterIdReasonExplanation !== 'v3-cluster' &&
101
+ (clusterDropdownId === 'dont-have-id' || dontKnowSelected);
61
102
  const clusterStateReset = () => {
62
103
  setSelectedReason('');
63
104
  setDontKnowSelected(false);
@@ -70,8 +111,15 @@ export function CaseOpenshiftClusterId() {
70
111
  openshiftClusterVersion: '',
71
112
  noClusterIdReasonExplanation: '',
72
113
  noClusterIdReason: '',
114
+ additionalCaseInformation: null,
73
115
  });
74
116
  };
117
+ const clearedClusterProductFields = {
118
+ openshiftClusterID: '',
119
+ openshiftClusterVersion: '',
120
+ noClusterIdReasonExplanation: '',
121
+ noClusterIdReason: '',
122
+ };
75
123
  const onDisplayNameChange = (val) => {
76
124
  setDisplayName(val);
77
125
  };
@@ -79,43 +127,24 @@ export function CaseOpenshiftClusterId() {
79
127
  const isClusterVisible = () => __awaiter(this, void 0, void 0, function* () {
80
128
  const hasCluster = yield isClusterIdEnabledForProduct(product);
81
129
  setShowClusterId(hasCluster);
82
- // when product changes from a product with cluster to a product without cluster, reset the clusterId
83
130
  const hasPreviousProduct = previousProduct !== undefined;
84
131
  const hasCurrentProduct = product !== undefined;
85
132
  //need to check if they are undefined as the data loads in and can cause eval against product version === undefined causing edge case to reset our cluster with logic as if product changed.
86
133
  const IsProductHasChanged = hasPreviousProduct && hasCurrentProduct && previousProduct !== product;
87
- const previousHadCluster = !isEmpty(previousProduct) && isClusterIdEnabledForProduct(previousProduct);
88
- const isResetClusterID = previousHadCluster && (!hasCluster || isOpenShiftV3) && IsProductHasChanged;
89
- if (isResetClusterID) {
90
- const caseDetails = {
91
- openshiftClusterID: '',
92
- openshiftClusterVersion: '',
93
- noClusterIdReasonExplanation: '',
94
- noClusterIdReason: '',
95
- };
96
- setCaseDetails(caseDispatch, caseDetails);
134
+ const currentIsClusterEnabled = hasCluster && !isOpenShiftV3;
135
+ const previousIsClusterEnabled = !isEmpty(previousProduct) && isClusterIdEnabledForProduct(previousProduct);
136
+ const shouldResetOnClusterProductBoundaryChange = IsProductHasChanged && previousIsClusterEnabled !== currentIsClusterEnabled;
137
+ if (shouldResetOnClusterProductBoundaryChange) {
138
+ setCaseDetails(caseDispatch, Object.assign(Object.assign({}, clearedClusterProductFields), { additionalCaseInformation: null }));
97
139
  setLocalOpenshiftClusterIDState('');
98
140
  clusterStateReset();
99
- if (!isEmpty(openshiftClusterID) || !isEmpty(openshiftClusterVersion)) {
100
- yield clusterIdUpdate({ openshiftClusterID: '', openshiftClusterVersion: '' }, false);
101
- }
102
- return;
103
- }
104
- // Switching onto a cluster product: restore reason fields from description and auto-select
105
- if (hasCluster && IsProductHasChanged && isEmpty(openshiftClusterID)) {
106
- const fromDescription = extractNoClusterIdFieldsFromDescription(description || '');
107
- const reason = noClusterIdReason || fromDescription.noClusterIdReason;
108
- const explanation = noClusterIdReasonExplanation || fromDescription.noClusterIdReasonExplanation;
109
- if (!isEmpty(reason) || (!isEmpty(explanation) && explanation !== 'v3-cluster')) {
110
- if (reason !== noClusterIdReason || explanation !== noClusterIdReasonExplanation) {
111
- setCaseDetails(caseDispatch, {
112
- noClusterIdReason: reason,
113
- noClusterIdReasonExplanation: explanation,
114
- });
115
- }
116
- setDontKnowSelected(true);
117
- setSelectedReason('dont-have-id');
118
- setLocalOpenshiftClusterIDState('');
141
+ const hasClusterRelatedData = !isEmpty(openshiftClusterID) ||
142
+ !isEmpty(openshiftClusterVersion) ||
143
+ !isEmpty(noClusterIdReason) ||
144
+ !isEmpty(noClusterIdReasonExplanation) ||
145
+ hasNoClusterIdFieldsInAdditionalCaseInformation(additionalCaseInformation);
146
+ if (hasClusterRelatedData) {
147
+ yield clusterIdUpdate(clearedClusterProductFields, false);
119
148
  }
120
149
  }
121
150
  });
@@ -123,25 +152,16 @@ export function CaseOpenshiftClusterId() {
123
152
  // eslint-disable-next-line react-hooks/exhaustive-deps
124
153
  }, [product]);
125
154
  /**
126
- * Hydrate cluster dropdown / reason UI from loaded case details
155
+ * Keep local invalid state in sync when a real cluster ID is present on the case.
127
156
  */
128
157
  useEffect(() => {
129
- const isClusterIdInvalid = getIsClusterIdInvalid(openshiftClusterID);
130
- setIsClusterIdInValid(isClusterIdInvalid);
158
+ setIsClusterIdInValid(getIsClusterIdInvalid(openshiftClusterID));
131
159
  if (!isEmpty(openshiftClusterID)) {
132
160
  setLocalOpenshiftClusterIDState(openshiftClusterID);
133
161
  setSelectedReason('');
134
162
  setDontKnowSelected(false);
135
- return;
136
163
  }
137
- if (!isEmpty(noClusterIdReason) ||
138
- (!isEmpty(noClusterIdReasonExplanation) && noClusterIdReasonExplanation !== 'v3-cluster')) {
139
- setDontKnowSelected(true);
140
- setSelectedReason('dont-have-id');
141
- setLocalOpenshiftClusterIDState('');
142
- }
143
- // eslint-disable-next-line react-hooks/exhaustive-deps
144
- }, [noClusterIdReason, noClusterIdReasonExplanation, openshiftClusterID, openshiftClusterVersion]);
164
+ }, [openshiftClusterID, openshiftClusterVersion]);
145
165
  const clusterIdUpdate = (caseDetails_1, ...args_1) => __awaiter(this, [caseDetails_1, ...args_1], void 0, function* (caseDetails, showToast = true) {
146
166
  if (showToast)
147
167
  setIsClusterIdUpdating(true);
@@ -153,9 +173,21 @@ export function CaseOpenshiftClusterId() {
153
173
  if (caseDetails.openshiftClusterVersion !== undefined) {
154
174
  caseUpdate.openshiftClusterVersion = caseDetails.openshiftClusterVersion;
155
175
  }
176
+ if (caseDetails.noClusterIdReason !== undefined) {
177
+ caseUpdate.noClusterIdReason = caseDetails.noClusterIdReason;
178
+ }
179
+ if (caseDetails.noClusterIdReasonExplanation !== undefined) {
180
+ caseUpdate.noClusterIdReasonExplanation = caseDetails.noClusterIdReasonExplanation;
181
+ }
156
182
  yield updateCaseDetailsGraphQL(caseDispatch, apolloClient, caseNumber, caseUpdate, false, {
157
183
  salesforceCaseId: caseId,
158
- existingCaseDetails: { product, version },
184
+ existingCaseDetails: {
185
+ product,
186
+ version,
187
+ noClusterIdReason,
188
+ noClusterIdReasonExplanation,
189
+ additionalCaseInformation,
190
+ },
159
191
  });
160
192
  if (showToast) {
161
193
  setIsClusterIdUpdating(false);
@@ -223,38 +255,37 @@ export function CaseOpenshiftClusterId() {
223
255
  yield clusterIdUpdate(caseDetails);
224
256
  }
225
257
  });
226
- const isDedicatedV3 = () => noClusterIdReason === 'Other' && noClusterIdReasonExplanation === 'v3-cluster';
258
+ const isDedicatedV3 = () => resolvedNoClusterIdReason === 'Other' && resolvedNoClusterIdReasonExplanation === 'v3-cluster';
227
259
  const v3Message = () => description.match(/Cluster Name: /g) ? (React.createElement(React.Fragment, null,
228
260
  "Your Cluster Name has been added to the description below. ",
229
261
  v3Tov4TransitionLink())) : (React.createElement(React.Fragment, null, v3Tov4TransitionLink()));
230
262
  const clusterIdDropdownFormInstructions = () => {
231
263
  const errorMessage = isClusterIdInvalid
232
264
  ? isInvalidErrorMessage()
233
- : isEmpty(openshiftClusterID) && isEmpty(selectedReason)
234
- ? discoverV4ClusterIdLinkError()
235
- : null;
265
+ : isEmpty(clusterDropdownId) || clusterDropdownId === 'dont-have-id' || clusterDropdownId === 'v3-cluster'
266
+ ? null
267
+ : discoverV4ClusterIdLinkError();
236
268
  const infoMessage = isDedicatedV3() ? v3Message() : discoverV4ClusterIdLink();
237
269
  return errorMessage ? errorMessage : infoMessage;
238
270
  };
239
271
  const onReasonExplanationInputBoxChanged = (explanationInput) => __awaiter(this, void 0, void 0, function* () {
240
272
  explanationInput = (explanationInput || '').trim();
241
- if (explanationInput) {
242
- const caseDetails = {
243
- noClusterIdReason: 'Other',
244
- openshiftClusterID: '',
245
- noClusterIdReasonExplanation: explanationInput,
246
- };
247
- try {
248
- setCaseDetails(caseDispatch, { noClusterIdReasonExplanation: explanationInput });
249
- yield clusterIdUpdate(caseDetails);
250
- }
251
- catch (e) {
252
- setCaseDetails(caseDispatch, { noClusterIdReasonExplanation });
253
- }
273
+ if (!explanationInput || explanationInput === (noClusterIdReasonExplanation || '').trim()) {
274
+ return;
275
+ }
276
+ const caseDetails = {
277
+ noClusterIdReason: 'Other',
278
+ openshiftClusterID: '',
279
+ noClusterIdReasonExplanation: explanationInput,
280
+ };
281
+ try {
282
+ setCaseDetails(caseDispatch, { noClusterIdReasonExplanation: explanationInput });
283
+ yield clusterIdUpdate(caseDetails);
284
+ }
285
+ catch (e) {
286
+ setCaseDetails(caseDispatch, { noClusterIdReasonExplanation });
254
287
  }
255
288
  });
256
- // eslint-disable-next-line react-hooks/exhaustive-deps
257
- const debounceFn = debounce(onReasonExplanationInputBoxChanged, 1000);
258
289
  const onReasonChange = (reason) => __awaiter(this, void 0, void 0, function* () {
259
290
  if (!reason || reason === noClusterIdReason)
260
291
  return;
@@ -274,7 +305,8 @@ export function CaseOpenshiftClusterId() {
274
305
  }
275
306
  setIsReasonUpdating(false);
276
307
  });
277
- const isInVaidNoClusterIdReason = isEmpty(noClusterIdReason) || (noClusterIdReason === 'Other' && isEmpty(noClusterIdReasonExplanation.trim()));
308
+ const isInVaidNoClusterIdReason = isEmpty(resolvedNoClusterIdReason) ||
309
+ (resolvedNoClusterIdReason === 'Other' && isEmpty((resolvedNoClusterIdReasonExplanation || '').trim()));
278
310
  if (!showClusterId || isFetchingCaseDetails) {
279
311
  return null;
280
312
  }
@@ -283,9 +315,12 @@ export function CaseOpenshiftClusterId() {
283
315
  }
284
316
  else {
285
317
  return (React.createElement(React.Fragment, null,
286
- React.createElement(OpenshiftDropdownV4, { openshiftDisplayName: displayName, setOpenshiftDisplayName: onDisplayNameChange, openshiftClusterIDState: localOpenshiftClusterIDState || selectedReason, onClusterIdStateUpdate: onClusterIdSave, isClusterIdInvalid: (isEmpty(localOpenshiftClusterIDState) && isEmpty(selectedReason)) || isClusterIdInvalid, clusterIdDropdownFormInstructions: !isExportingPDF ? clusterIdDropdownFormInstructions() : undefined, onClusterClear: resetClusterData, isV3: product !== 'OpenShift Container Platform', isDisabled: isClusterIdUpdating, noClusterIdReasonExplanation: noClusterIdReasonExplanation }),
287
- noClusterIdReasonExplanation !== 'v3-cluster' &&
288
- (dontKnowSelected || noClusterIdReasonExplanation || noClusterIdReason) && (React.createElement(NoClusterIDReasonSelector, { noClusterIdReasonExplanation: noClusterIdReasonExplanation, noClusterIdReason: noClusterIdReason, onReasonInputBoxChanged: debounceFn, onReasonChange: onReasonChange, isInValid: isInVaidNoClusterIdReason, isCustomer: isCustomer, isDisabled: isReasonUpdating })),
318
+ React.createElement(OpenshiftDropdownV4, { openshiftDisplayName: displayName, setOpenshiftDisplayName: onDisplayNameChange, openshiftClusterIDState: clusterDropdownId || '', onClusterIdStateUpdate: onClusterIdSave, isClusterIdInvalid: isEmpty(clusterDropdownId) ||
319
+ clusterDropdownId === 'dont-have-id' ||
320
+ clusterDropdownId === 'v3-cluster'
321
+ ? false
322
+ : isClusterIdInvalid, clusterIdDropdownFormInstructions: !isExportingPDF ? clusterIdDropdownFormInstructions() : undefined, onClusterClear: resetClusterData, isV3: product !== 'OpenShift Container Platform', isDisabled: isClusterIdUpdating, noClusterIdReasonExplanation: resolvedNoClusterIdReasonExplanation || '' }),
323
+ shouldShowNoClusterReasonSelector && (React.createElement(NoClusterIDReasonSelector, { noClusterIdReasonExplanation: resolvedNoClusterIdReasonExplanation || '', noClusterIdReason: resolvedNoClusterIdReason || '', onReasonInputBoxBlur: onReasonExplanationInputBoxChanged, onReasonChange: onReasonChange, isInValid: isInVaidNoClusterIdReason, isCustomer: isCustomer, isDisabled: isReasonUpdating })),
289
324
  React.createElement(LoadingIndicator, { show: isClusterIdUpdating, size: "xs" })));
290
325
  }
291
326
  }
@@ -6,6 +6,7 @@ interface IProps {
6
6
  feedback: number;
7
7
  onFeedBackUpdate: (id: string, feedback: number) => void;
8
8
  accountNumber: string;
9
+ onReply: (author: string, commentId: string, timestamp: string) => void;
9
10
  showJumpToComment?: boolean;
10
11
  onJumpToComment?: (commentId: string) => void;
11
12
  downloadAttachment: ({ caseNumber, uuid, name }: {
@@ -1 +1 @@
1
- {"version":3,"file":"CaseComments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AA2BvE,OAAO,KAAwC,MAAM,OAAO,CAAC;AAU7D,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChH;AAED,QAAA,MAAM,YAAY,4EAgUhB,CAAC;AAEH,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"CaseComments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AA2BvE,OAAO,KAAwC,MAAM,OAAO,CAAC;AAU7D,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChH;AAED,QAAA,MAAM,YAAY,4EA8UhB,CAAC;AAEH,eAAe,YAAY,CAAC"}
@@ -251,6 +251,8 @@ const CaseComments = React.forwardRef((props, ref) => {
251
251
  React.createElement("span", { className: "pull-right pf-v6-l-flex pf-m-align-items-center" },
252
252
  props.showJumpToComment && (React.createElement(DiscussionItemLink, { onClick: onJumpToComment(props.comment.id), discussionType: DiscussionType.COMMENT, itemId: props.comment.id, caseNumber: caseNumber, isCopyLink: false },
253
253
  React.createElement(Trans, null, "Jump to comment"))),
254
- React.createElement(JumpAndCopyLink, { caseNumber: caseNumber, cardId: props.comment.id, discussionType: DiscussionType.COMMENT })))));
254
+ React.createElement(JumpAndCopyLink, { caseNumber: caseNumber, cardId: props.comment.id, discussionType: DiscussionType.COMMENT }),
255
+ React.createElement("button", { onClick: () => props.onReply(props.comment.lastModifiedById, props.comment.id, props.comment.lastModifiedDate), className: `btn btn-app btn-link case-reply-button ${isExportingPDF ? 'hide-in-pdf' : ''}`, "data-tracking-id": "case-comment-reply", type: "button" },
256
+ React.createElement(Trans, null, "Reply"))))));
255
257
  });
256
258
  export default CaseComments;
@@ -1 +1 @@
1
- {"version":3,"file":"CaseDiscussion.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAkBvE,OAAO,KAAoE,MAAM,OAAO,CAAC;AAoCzF,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAClD;AAOD,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAAK,EAAE,MAAM,qBAugBnD"}
1
+ {"version":3,"file":"CaseDiscussion.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAkBvE,OAAO,KAAoE,MAAM,OAAO,CAAC;AAsCzF,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAClD;AAOD,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAAK,EAAE,MAAM,qBAqhBnD"}
@@ -26,7 +26,7 @@ import { AutoSizer, CellMeasurer, CellMeasurerCache, List, WindowScroller } from
26
26
  import { useCaseDispatch, useCaseSelector } from '../../../../context/CaseContext';
27
27
  import { useCaseDetailsPageDispatchContext, useCaseDetailsPageStateContext, } from '../../../../context/CaseDetailsPageContext';
28
28
  import { useCaseDiscussionTabDispatchContext, useCaseDiscussionTabStateContext, } from '../../../../context/CaseDiscussionTabContext';
29
- import { discussionSortOrderConst, DiscussionType, setDiscussions, setSort, updateAttachment, updateAttacmentsAfterRemoval, updateDiscussionStateAttachments, } from '../../../../reducers/CaseDiscussionTabReducer';
29
+ import { clearReplyingTo, discussionSortOrderConst, DiscussionType, setDiscussions, setReplyingTo, setSort, updateAttachment, updateAttacmentsAfterRemoval, updateDiscussionStateAttachments, } from '../../../../reducers/CaseDiscussionTabReducer';
30
30
  import { setCaseState } from '../../../../reducers/CaseReducer';
31
31
  import { AttachmentContextProvider } from '../../../shared/fileUpload/reducer/AttachmentReducerContext';
32
32
  import { PDFContext } from '../../PDFContainer';
@@ -52,7 +52,7 @@ export default function CaseDiscussion(props) {
52
52
  const urlSearchParams = getUrlParsedParams(useLocation().search);
53
53
  const discussionIdFromUrl = ((urlSearchParams === null || urlSearchParams === void 0 ? void 0 : urlSearchParams.commentId) || (urlSearchParams === null || urlSearchParams === void 0 ? void 0 : urlSearchParams.attachmentId));
54
54
  const activeDiscussionElementRef = useRef(null);
55
- const { sort, discussionFiltersListState, allDiscussions } = useCaseDiscussionTabStateContext();
55
+ const { sort, discussionFiltersListState, allDiscussions, replyingToAuthor, replyingToTimestamp } = useCaseDiscussionTabStateContext();
56
56
  const { globalMetadataState: { navBarRef }, } = useGlobalStateContext();
57
57
  const dispatchDiscussion = useCaseDiscussionTabDispatchContext();
58
58
  const { caseDetailsPageState: { caseAttachmentHydra }, } = useCaseDetailsPageStateContext();
@@ -147,6 +147,13 @@ export default function CaseDiscussion(props) {
147
147
  }
148
148
  dtmTrackEventCaseStepEncountered('comment', caseNumber, product, version);
149
149
  });
150
+ const onReply = (author, commentId, timestamp) => {
151
+ setReplyingTo(dispatchDiscussion, author, commentId, timestamp);
152
+ scrollIntoView(props.tabRef, { navBarRef, timeout: 0, onlyIfNotInViewport: true, offset: 30 });
153
+ };
154
+ const onClearReply = () => {
155
+ clearReplyingTo(dispatchDiscussion);
156
+ };
150
157
  /** Strips special chars to prevent regex injection, then HTML-escapes via DOM round-trip to prevent XSS. */
151
158
  const sanitizedSearchInput = (value) => {
152
159
  if (!value)
@@ -247,7 +254,7 @@ export default function CaseDiscussion(props) {
247
254
  if (isEmpty(discussion) || isEmpty(discussion.item))
248
255
  return null;
249
256
  return (React.createElement("div", { "data-tracking-id": "discussion-elements", key: discussion.item.id },
250
- discussion.discussionType === DiscussionType.COMMENT && (React.createElement(CaseComments, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, comment: discussion.item, onFeedBackUpdate: () => { }, feedback: discussion.feedback, accountNumber: props.accountNumber, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment, downloadAttachment: downloadAttachment })),
257
+ discussion.discussionType === DiscussionType.COMMENT && (React.createElement(CaseComments, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, comment: discussion.item, onFeedBackUpdate: () => { }, feedback: discussion.feedback, accountNumber: props.accountNumber, onReply: onReply, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment, downloadAttachment: downloadAttachment })),
251
258
  discussion.discussionType === DiscussionType.ATTACHMENT && (React.createElement(CaseAttachment, { attachment: discussion.item, onAttachmentRemove: onAttachmentRemove, onMetadataUpdate: onMetadataUpdate, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment, downloadAttachment: downloadAttachment, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null }))));
252
259
  };
253
260
  const rowRenderer = ({ index, parent, key, style, }) => {
@@ -321,7 +328,7 @@ export default function CaseDiscussion(props) {
321
328
  return (React.createElement(React.Fragment, null,
322
329
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading post comment section') } },
323
330
  React.createElement(AttachmentContextProvider, null,
324
- React.createElement(PostComment, { caseNumber: caseNumber, allDiscussions: allDiscussions, onCommentAdded: onCommentAdded, onAttachmentAdded: onAttachmentAdded, onAttachmentRemove: onAttachmentRemove }))),
331
+ React.createElement(PostComment, { caseNumber: caseNumber, allDiscussions: allDiscussions, onCommentAdded: onCommentAdded, onAttachmentAdded: onAttachmentAdded, onAttachmentRemove: onAttachmentRemove, replyingToAuthor: replyingToAuthor, replyingToTimestamp: replyingToTimestamp, onClearReply: onClearReply }))),
325
332
  props.commentsLoading && allDiscussions.length === 0 && React.createElement(LoadingIndicator, { size: "sm" }),
326
333
  props.commentsError && allDiscussions.length === 0 && (React.createElement(AlertMessage, { variant: AlertType.DANGER, show: true, title: t('Failed to load comments. Try refreshing.') })),
327
334
  !props.commentsLoading && !props.commentsError && allDiscussions.length === 0 && (React.createElement(Trans, null, "No comments")),
@@ -2,12 +2,14 @@ import { Dispatch, SetStateAction } from 'react';
2
2
  interface UseCommentDraftsParams {
3
3
  caseNumber: string;
4
4
  loggedInUserSSO: string;
5
+ isInternal: boolean;
5
6
  commentSignature: string;
7
+ canPostPrivateComments: boolean;
6
8
  setCommentText: Dispatch<SetStateAction<string>>;
7
- setIsPublic: Dispatch<SetStateAction<boolean | undefined>>;
9
+ setIsPublic: Dispatch<SetStateAction<boolean>>;
8
10
  applySignature: (text: string) => void;
9
11
  }
10
- export declare function useCommentDrafts({ caseNumber, loggedInUserSSO, commentSignature, setCommentText, setIsPublic, applySignature, }: UseCommentDraftsParams): {
12
+ export declare function useCommentDrafts({ caseNumber, loggedInUserSSO, isInternal, commentSignature, canPostPrivateComments, setCommentText, setIsPublic, applySignature, }: UseCommentDraftsParams): {
11
13
  saveDraft: (...args: any[]) => void;
12
14
  clearDraft: () => Promise<void>;
13
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useCommentDrafts.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAsB,MAAM,OAAO,CAAC;AAMrE,UAAU,sBAAsB;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,WAAW,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,EAC7B,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,cAAc,GACjB,EAAE,sBAAsB;;;EAqDxB"}
1
+ {"version":3,"file":"useCommentDrafts.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAsB,MAAM,OAAO,CAAC;AAMrE,UAAU,sBAAsB;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,OAAO,CAAC;IAChC,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,WAAW,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,EAC7B,UAAU,EACV,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,WAAW,EACX,cAAc,GACjB,EAAE,sBAAsB;;;EA4DxB"}
@@ -11,16 +11,22 @@ import { debounce } from '@patternfly/react-core';
11
11
  import { useEffect, useMemo } from 'react';
12
12
  import { CaseDetailsCacheNamespaces } from '../../../../../enums/cache';
13
13
  import { CaseDetailsCacheUtils } from '../../../../../utils/caseDetailsCacheUtils';
14
- export function useCommentDrafts({ caseNumber, loggedInUserSSO, commentSignature, setCommentText, setIsPublic, applySignature, }) {
14
+ export function useCommentDrafts({ caseNumber, loggedInUserSSO, isInternal, commentSignature, canPostPrivateComments, setCommentText, setIsPublic, applySignature, }) {
15
15
  const saveDraft = useMemo(() => debounce(function (value, publicFlag) {
16
16
  return __awaiter(this, void 0, void 0, function* () {
17
+ const div = document.createElement('div');
18
+ div.innerHTML = value;
19
+ const plainText = (div.textContent || '').trim();
20
+ if (!plainText || plainText === commentSignature) {
21
+ return;
22
+ }
17
23
  const { value: prevDraftComments = {} } = (yield CaseDetailsCacheUtils.get(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO)) || {};
18
- prevDraftComments[caseNumber] = { text: value, privateFlag: !publicFlag };
24
+ prevDraftComments[caseNumber] = { text: value, privateFlag: !(publicFlag !== null && publicFlag !== void 0 ? publicFlag : true) };
19
25
  CaseDetailsCacheUtils.set(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO, {
20
26
  value: prevDraftComments,
21
27
  });
22
28
  });
23
- }, 500), [caseNumber, loggedInUserSSO]);
29
+ }, 500), [caseNumber, commentSignature, loggedInUserSSO]);
24
30
  const clearDraft = () => __awaiter(this, void 0, void 0, function* () {
25
31
  const { value: prevDraftComments = {} } = (yield CaseDetailsCacheUtils.get(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO)) || {};
26
32
  delete prevDraftComments[caseNumber];
@@ -41,8 +47,9 @@ export function useCommentDrafts({ caseNumber, loggedInUserSSO, commentSignature
41
47
  if (!/<[a-z][\s\S]*>/i.test(draftText)) {
42
48
  draftText = `<p>${draftText}</p>`;
43
49
  }
50
+ setCommentText(draftText);
44
51
  applySignature(draftText);
45
- if (draft.privateFlag)
52
+ if (draft.privateFlag && canPostPrivateComments)
46
53
  setIsPublic(false);
47
54
  });
48
55
  }
@@ -13,6 +13,9 @@ interface IProps {
13
13
  */
14
14
  defaultIsPublic?: boolean;
15
15
  allDiscussions: IDiscussion[];
16
+ replyingToAuthor?: string | null;
17
+ replyingToTimestamp?: string | null;
18
+ onClearReply?: () => void;
16
19
  }
17
20
  export declare function PostComment(props: IProps): React.JSX.Element;
18
21
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"PostComment.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment.tsx"],"names":[],"mappings":"AASA,OAAO,KAA+D,MAAM,OAAO,CAAC;AAOpF,OAAO,EAAE,WAAW,EAAE,MAAM,+CAA+C,CAAC;AAmB5E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,WAAW,EAAE,CAAC;CACjC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,qBA0XxC"}
1
+ {"version":3,"file":"PostComment.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA+D,MAAM,OAAO,CAAC;AAOpF,OAAO,EAAE,WAAW,EAAE,MAAM,+CAA+C,CAAC;AAmB5E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,WAAW,EAAE,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,qBA4ZxC"}