@rh-support/troubleshoot 2.6.295 → 2.6.299
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/ActiveCustomerEscalation/RequestEscalationModal.js +4 -7
- package/lib/esm/components/CaseEditView/Case.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Case.js +42 -12
- package/lib/esm/components/CaseEditView/CaseDetailsTabs.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseDetailsTabs.js +17 -7
- package/lib/esm/components/CaseEditView/CaseOverview/CaseStatus.d.ts +1 -2
- package/lib/esm/components/CaseEditView/CaseOverview/CaseStatus.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseOverview/CaseStatus.js +8 -6
- package/lib/esm/components/CaseEditView/CaseOverview/index.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseOverview/index.js +17 -12
- package/lib/esm/components/CaseEditView/ConfirmationModals/ReopenCaseModal.d.ts +1 -3
- package/lib/esm/components/CaseEditView/ConfirmationModals/ReopenCaseModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/ConfirmationModals/ReopenCaseModal.js +3 -4
- package/lib/esm/components/CaseEditView/RequestRemoteSession/ESSRemoteSessionModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/ESSRemoteSessionModal.js +4 -7
- package/lib/esm/components/CaseEditView/RequestRemoteSession/NewEssTermsModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/NewEssTermsModal.js +4 -30
- package/lib/esm/components/CaseEditView/RequestRemoteSession/RemoteSessionAgreementModal.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/RequestRemoteSession/RemoteSessionAgreementModal.js +4 -30
- package/lib/esm/components/CaseEditView/RequestRemoteSession/remoteSessionUtils.d.ts +3 -0
- package/lib/esm/components/CaseEditView/RequestRemoteSession/remoteSessionUtils.d.ts.map +1 -0
- package/lib/esm/components/CaseEditView/RequestRemoteSession/remoteSessionUtils.js +22 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.d.ts +4 -2
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.js +110 -148
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.d.ts +15 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.d.ts.map +1 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.js +19 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.d.ts +17 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.d.ts.map +1 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.js +49 -0
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts +6 -2
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.js +147 -241
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/CaseHistory.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/CaseHistory.js +3 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.css +4 -4
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.d.ts +35 -3
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseHistory/Timeline.js +63 -224
- package/lib/esm/components/CaseEditView/Tabs/CaseSummary/CaseSummary.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseSummary/CaseSummary.js +7 -2
- package/lib/esm/components/CaseEditView/Tabs/RMEEscalations/RMEEscalationList.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/RMEEscalations/RMEEscalationList.js +4 -7
- package/lib/esm/components/CaseManagement/Cep.d.ts.map +1 -1
- package/lib/esm/components/CaseManagement/Cep.js +4 -7
- package/lib/esm/components/ProductSelector/NewProductVersionSelector.d.ts.map +1 -1
- package/lib/esm/components/ProductSelector/NewProductVersionSelector.js +18 -4
- package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.d.ts.map +1 -1
- package/lib/esm/components/UpdateSeverityModal/UpdateSeverityModal.js +4 -7
- package/lib/esm/components/shared/usePostComment.d.ts.map +1 -1
- package/lib/esm/components/shared/usePostComment.js +6 -10
- package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.d.ts.map +1 -1
- package/lib/esm/components/wizardLayout/GlobalTroubleshootEffects.js +0 -2
- package/lib/esm/context/CaseContext.d.ts.map +1 -1
- package/lib/esm/hooks/useCaseComments/caseCommentMutation.d.ts +4 -0
- package/lib/esm/hooks/useCaseComments/caseCommentMutation.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/caseCommentMutation.js +12 -0
- package/lib/esm/hooks/useCaseComments/caseCommentsQuery.d.ts +4 -0
- package/lib/esm/hooks/useCaseComments/caseCommentsQuery.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/caseCommentsQuery.js +55 -0
- package/lib/esm/hooks/useCaseComments/index.d.ts +7 -0
- package/lib/esm/hooks/useCaseComments/index.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/index.js +5 -0
- package/lib/esm/hooks/useCaseComments/mapCaseComment.d.ts +25 -0
- package/lib/esm/hooks/useCaseComments/mapCaseComment.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/mapCaseComment.js +66 -0
- package/lib/esm/hooks/useCaseComments/types.d.ts +80 -0
- package/lib/esm/hooks/useCaseComments/types.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/types.js +1 -0
- package/lib/esm/hooks/useCaseComments/useCaseComments.d.ts +16 -0
- package/lib/esm/hooks/useCaseComments/useCaseComments.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/useCaseComments.js +25 -0
- package/lib/esm/hooks/useCaseComments/useCreateCaseComment.d.ts +19 -0
- package/lib/esm/hooks/useCaseComments/useCreateCaseComment.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseComments/useCreateCaseComment.js +33 -0
- package/lib/esm/hooks/useCaseHistory.d.ts +26 -0
- package/lib/esm/hooks/useCaseHistory.d.ts.map +1 -0
- package/lib/esm/hooks/useCaseHistory.js +98 -0
- package/lib/esm/models/caseHistory.d.ts +80 -0
- package/lib/esm/models/caseHistory.d.ts.map +1 -0
- package/lib/esm/models/caseHistory.js +1 -0
- package/lib/esm/reducers/CaseConstNTypes.d.ts +0 -1
- package/lib/esm/reducers/CaseConstNTypes.d.ts.map +1 -1
- package/lib/esm/reducers/CaseConstNTypes.js +0 -1
- package/lib/esm/reducers/CaseDiscussionTabReducer.d.ts +0 -2
- package/lib/esm/reducers/CaseDiscussionTabReducer.d.ts.map +1 -1
- package/lib/esm/reducers/CaseDiscussionTabReducer.js +1 -28
- package/lib/esm/reducers/CaseReducer.d.ts.map +1 -1
- package/lib/esm/reducers/CaseReducer.js +14 -4
- package/lib/esm/utils/TimelineUtils.d.ts +41 -0
- package/lib/esm/utils/TimelineUtils.d.ts.map +1 -0
- package/lib/esm/utils/TimelineUtils.js +134 -0
- package/lib/esm/utils/caseHistoryUtils.d.ts +66 -0
- package/lib/esm/utils/caseHistoryUtils.d.ts.map +1 -0
- package/lib/esm/utils/caseHistoryUtils.js +165 -0
- package/package.json +5 -5
|
@@ -1,23 +1,16 @@
|
|
|
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
1
|
import './Timeline.css';
|
|
11
|
-
import { caseHistory } from '@cee-eng/hydrajs';
|
|
12
2
|
import { Avatar, Button, DatePicker, EmptyState, EmptyStateBody, EmptyStateVariant, MenuToggle, Pagination, SearchInput, Select, SelectOption, Spinner, } from '@patternfly/react-core';
|
|
13
3
|
import ExclamationCircleIcon from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
|
|
14
4
|
import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon';
|
|
15
5
|
import { haltEvent } from '@rh-support/utils';
|
|
16
|
-
import { format,
|
|
6
|
+
import { format, isSameDay, parse, parseISO } from 'date-fns';
|
|
17
7
|
import debounce from 'lodash/debounce';
|
|
18
8
|
import isEmpty from 'lodash/isEmpty';
|
|
19
9
|
import React, { useEffect, useRef, useState } from 'react';
|
|
20
10
|
import { Trans, useTranslation } from 'react-i18next';
|
|
11
|
+
import { useCaseHistory } from '../../../../hooks/useCaseHistory';
|
|
12
|
+
import { getFieldDisplayName } from '../../../../utils/caseHistoryUtils';
|
|
13
|
+
import { applyPostProcessing, handleFieldChange } from '../../../../utils/TimelineUtils';
|
|
21
14
|
const CustomHighlighter = ({ search, children, highlightDate, }) => {
|
|
22
15
|
const createHighlight = (text) => React.createElement("mark", { className: "timeline-highlight" }, text);
|
|
23
16
|
if (highlightDate) {
|
|
@@ -25,7 +18,7 @@ const CustomHighlighter = ({ search, children, highlightDate, }) => {
|
|
|
25
18
|
}
|
|
26
19
|
if (search) {
|
|
27
20
|
const escapedSearch = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
28
|
-
const regex = new RegExp(`(${escapedSearch})`, '
|
|
21
|
+
const regex = new RegExp(`(${escapedSearch})`, 'i');
|
|
29
22
|
const parts = children.split(regex);
|
|
30
23
|
return React.createElement(React.Fragment, null, parts.map((part, index) => (regex.test(part) ? createHighlight(part) : part)));
|
|
31
24
|
}
|
|
@@ -52,193 +45,58 @@ const TimelineEvent = ({ date, text, side, user, useAvatar, searchValue, highlig
|
|
|
52
45
|
text && (React.createElement("p", { className: `content-time-${side}-history` },
|
|
53
46
|
React.createElement(CustomHighlighter, { search: searchValue || '' }, text))))));
|
|
54
47
|
};
|
|
55
|
-
const
|
|
48
|
+
const DEFAULT_AVATAR_SRC = 'https://www.patternfly.org/images/668560cd.svg';
|
|
49
|
+
const TimelineNode = React.forwardRef(({ leftEvent, rightEvent, user, useAvatar, photoUrl, searchValue, highlightDate }, ref) => {
|
|
50
|
+
const [imgSrc, setImgSrc] = useState(photoUrl || DEFAULT_AVATAR_SRC);
|
|
56
51
|
return (React.createElement("div", { className: "timeline-node", role: "region", "aria-label": "Timeline node" },
|
|
57
52
|
leftEvent && (React.createElement(TimelineEvent, Object.assign({}, leftEvent, { side: "left", useAvatar: useAvatar, searchValue: searchValue, highlightDate: highlightDate }))),
|
|
58
|
-
React.createElement("div", { ref: ref, "aria-label": `${useAvatar ? 'User profile picture' : 'Timeline marker'}`, tabIndex: -1 }, useAvatar ? (React.createElement(Avatar, { src:
|
|
53
|
+
React.createElement("div", { ref: ref, "aria-label": `${useAvatar ? 'User profile picture' : 'Timeline marker'}`, tabIndex: -1 }, useAvatar ? (React.createElement(Avatar, { src: imgSrc, className: `timeline-avatar timeline-avatar-${user}`, alt: `${user}'s avatar`, onError: () => setImgSrc(DEFAULT_AVATAR_SRC) })) : (React.createElement("div", { className: `timeline-marker timeline-${user}` }))),
|
|
59
54
|
rightEvent && React.createElement(TimelineEvent, Object.assign({}, rightEvent, { side: "right", searchValue: searchValue }))));
|
|
60
55
|
});
|
|
61
56
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* @returns {string} The formatted text string.
|
|
57
|
+
* Builds the display text for a "Change" history item by resolving values and
|
|
58
|
+
* delegating to field-specific formatters.
|
|
65
59
|
*/
|
|
66
|
-
const applyReplacements = (item) => {
|
|
60
|
+
export const applyReplacements = (item) => {
|
|
61
|
+
var _a, _b;
|
|
67
62
|
if (!item || typeof item !== 'object')
|
|
68
63
|
return '';
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
EntitlementId: 'Entitlement',
|
|
75
|
-
AccountId: 'Account',
|
|
76
|
-
OwnerId: 'Owner',
|
|
77
|
-
BusinessHoursId: 'Business Hours',
|
|
78
|
-
FolderId__c: 'Case Group',
|
|
79
|
-
Status: 'Status',
|
|
80
|
-
Customer_Escalation__c: 'Customer Escalation',
|
|
81
|
-
SlaStartDate: 'SLA Start Date',
|
|
82
|
-
Case_Language__c: 'Case Language',
|
|
83
|
-
Alternate_Id__c: 'Personal reference number',
|
|
84
|
-
SBR_Group__c: 'SBR Group',
|
|
85
|
-
};
|
|
86
|
-
// https://help.salesforce.com/s/articleView?id=000384484&type=1
|
|
87
|
-
// adding in option for multiselect fields provided by salesforce.
|
|
88
|
-
// in future for more multiselect fields just add to below array.
|
|
89
|
-
const multiSelectFields = ['SBR_Group__c'];
|
|
90
|
-
// language codes to language names
|
|
91
|
-
const languageCodeMapping = {
|
|
92
|
-
de: 'German',
|
|
93
|
-
en: 'English',
|
|
94
|
-
es: 'Spanish',
|
|
95
|
-
fr: 'French',
|
|
96
|
-
it: 'Italian',
|
|
97
|
-
pt: 'Portuguese',
|
|
98
|
-
ko: 'Korean',
|
|
99
|
-
ja: 'Japanese',
|
|
100
|
-
zh: 'Chinese',
|
|
101
|
-
zh_CN: 'Chinese',
|
|
102
|
-
zh_HK: 'Chinese (Hong Kong)',
|
|
103
|
-
zh_TW: 'Chinese (Taiwan)',
|
|
104
|
-
ru: 'Russian',
|
|
105
|
-
};
|
|
106
|
-
// field display names to prefix keys used in item properties
|
|
107
|
-
const keyMap = {
|
|
108
|
-
Product: 'product',
|
|
109
|
-
Version: 'version',
|
|
110
|
-
Account: 'account',
|
|
111
|
-
Contact: 'contact',
|
|
112
|
-
Entitlement: 'entitlement',
|
|
113
|
-
'Business Hours': 'businessHours',
|
|
114
|
-
Owner: 'queueNameOwner',
|
|
115
|
-
'Customer Escalation': 'customerEscalation',
|
|
116
|
-
'Case Group': 'caseGroup',
|
|
117
|
-
'SLA Start Date': 'slaStartDate',
|
|
118
|
-
'Case Language': 'caseLanguage',
|
|
119
|
-
'Personal reference number': 'alternateId',
|
|
120
|
-
};
|
|
121
|
-
// get the mapped display name for a field
|
|
122
|
-
const getMappedFieldName = (fieldName) => fieldNameMapping[fieldName] || item.fieldLabel || fieldName || '';
|
|
123
|
-
// get the new or old value using the prefix
|
|
124
|
-
const getNameValue = (prefix) => item[`${keyMap[getMappedFieldName(item.fieldName)]}${prefix}Name`] ||
|
|
125
|
-
item[`${prefix}Value`] ||
|
|
126
|
-
item[`${prefix.toLowerCase()}Value`] ||
|
|
127
|
-
'';
|
|
128
|
-
// formatting functions
|
|
129
|
-
const formatLanguageChange = (fieldName, oldLanguage, newLanguage) => `changed ${fieldName} from ${oldLanguage} to ${newLanguage}`;
|
|
130
|
-
const formatSimpleChange = (fieldName, value) => `set ${fieldName} to ${value}`;
|
|
131
|
-
const formatBooleanChange = (fieldName, value) => `set ${fieldName} to ${value}`;
|
|
132
|
-
// get field name and values
|
|
133
|
-
const fieldName = getMappedFieldName(item.fieldName);
|
|
134
|
-
const newValue = getNameValue('New');
|
|
135
|
-
const oldValue = getNameValue('Old');
|
|
136
|
-
let newText = '';
|
|
137
|
-
// special field handling below, useful for future exposed case history fields etc / api changes
|
|
138
|
-
switch (item.fieldName) {
|
|
139
|
-
case 'Case_Language__c': {
|
|
140
|
-
const newLanguage = languageCodeMapping[item.newValue] || item.newValue;
|
|
141
|
-
const oldLanguage = languageCodeMapping[item.oldValue] || item.oldValue;
|
|
142
|
-
newText =
|
|
143
|
-
item.oldValue && item.newValue
|
|
144
|
-
? formatLanguageChange(fieldName, oldLanguage, newLanguage)
|
|
145
|
-
: formatSimpleChange(fieldName, newLanguage || 'empty');
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
case 'OwnerId':
|
|
149
|
-
if (item.createdByUserName)
|
|
150
|
-
newText = formatSimpleChange(fieldName, item.createdByUserName);
|
|
151
|
-
break;
|
|
152
|
-
case 'Status':
|
|
153
|
-
newText =
|
|
154
|
-
item.oldValue && item.newValue
|
|
155
|
-
? `changed ${fieldName} from ${item.oldValue} to ${item.newValue}`
|
|
156
|
-
: formatSimpleChange(fieldName, item.newValue || 'empty');
|
|
157
|
-
break;
|
|
158
|
-
case 'Customer_Escalation__c':
|
|
159
|
-
if (item.createdByUserName)
|
|
160
|
-
newText = 'started Escalation for this ticket';
|
|
161
|
-
break;
|
|
162
|
-
case 'SlaStartDate':
|
|
163
|
-
if (item.newValue)
|
|
164
|
-
newText = formatSimpleChange(fieldName, item.newValue);
|
|
165
|
-
break;
|
|
166
|
-
case 'RemoteSessionTermsAckedBy__c':
|
|
167
|
-
newText = 'Acked Remote Rider terms';
|
|
168
|
-
break;
|
|
169
|
-
default:
|
|
170
|
-
if (oldValue && newValue) {
|
|
171
|
-
if (multiSelectFields.includes(item.fieldName)) {
|
|
172
|
-
// in salesforce multi-select picklist values are stored as a single string, with each value separated by a semicolon
|
|
173
|
-
const oldValues = oldValue.split(';').map((s) => s.trim());
|
|
174
|
-
const newValues = newValue.split(';').map((s) => s.trim());
|
|
175
|
-
const added = newValues.filter((nv) => !oldValues.includes(nv));
|
|
176
|
-
const removed = oldValues.filter((ov) => !newValues.includes(ov));
|
|
177
|
-
if (added.length > 0 && removed.length === 0) {
|
|
178
|
-
newText = `added ${added.join(', ')} to ${fieldName}`;
|
|
179
|
-
}
|
|
180
|
-
else if (removed.length > 0 && added.length === 0) {
|
|
181
|
-
newText = `removed ${removed.join(', ')} from ${fieldName}`;
|
|
182
|
-
}
|
|
183
|
-
else if (added.length > 0 && removed.length > 0) {
|
|
184
|
-
newText = `changed ${fieldName}, added ${added.join(', ')} and removed ${removed.join(', ')}`;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
newText = `changed ${fieldName} from ${oldValue} to ${newValue}`;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
newText = `changed ${fieldName} from ${oldValue} to ${newValue}`;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
else if (newValue) {
|
|
195
|
-
newText = formatSimpleChange(fieldName, newValue);
|
|
196
|
-
}
|
|
197
|
-
else if (oldValue && (newValue === undefined || newValue === '')) {
|
|
198
|
-
newText = `removed ${fieldName}, was ${oldValue}`;
|
|
199
|
-
}
|
|
200
|
-
else if (item.newValue !== undefined) {
|
|
201
|
-
newText = formatSimpleChange(fieldName, item.newValue);
|
|
202
|
-
}
|
|
203
|
-
break;
|
|
204
|
-
}
|
|
205
|
-
if (typeof item.newValue === 'boolean')
|
|
206
|
-
newText = formatBooleanChange(fieldName, item.newValue);
|
|
207
|
-
if (typeof newText === 'string')
|
|
208
|
-
newText = newText.replace(/Problem Statement/g, 'Title');
|
|
209
|
-
if (typeof newText === 'string')
|
|
210
|
-
newText = newText.replace(/Case Type/g, 'Support Type');
|
|
211
|
-
return newText;
|
|
64
|
+
const fieldName = item.displayName || getFieldDisplayName(item.fieldName) || item.fieldName;
|
|
65
|
+
const newValue = String((_a = item.newValue) !== null && _a !== void 0 ? _a : '');
|
|
66
|
+
const oldValue = String((_b = item.oldValue) !== null && _b !== void 0 ? _b : '');
|
|
67
|
+
const text = handleFieldChange(item, fieldName, oldValue, newValue);
|
|
68
|
+
return applyPostProcessing(text, item);
|
|
212
69
|
};
|
|
213
|
-
|
|
214
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Converts normalized history items into timeline node data for rendering.
|
|
72
|
+
*
|
|
73
|
+
* Applies a secondary filter (excludes `FolderId__c` and `OwnerId` whose resolved
|
|
74
|
+
* display names are unavailable), then maps each item to a left (date/time) and
|
|
75
|
+
* right (user action text) event pair. Avatar/date-header boundaries are computed
|
|
76
|
+
* sequentially: a new boundary is set on the first item, user change, or date change.
|
|
77
|
+
*/
|
|
78
|
+
export const transformApiResponseToTimelineData = (apiResponse) => {
|
|
215
79
|
let previousUser = null;
|
|
216
80
|
let previousDate = null;
|
|
217
81
|
const timelineEvents = apiResponse.historyItems
|
|
218
|
-
//
|
|
82
|
+
// Second-layer field-name filter on top of filterSfdcIdEntries (which is pattern-based).
|
|
83
|
+
// FolderId__c (Case Group) and OwnerId are excluded because their resolved display
|
|
84
|
+
// names (queue name, owner name) are not available in the history payload.
|
|
219
85
|
.filter((item) => item.fieldName !== 'FolderId__c' && item.fieldName !== 'OwnerId')
|
|
220
86
|
.map((item, index) => {
|
|
221
87
|
const currentUser = item.createdByUserName;
|
|
222
|
-
|
|
223
|
-
if (typeof item.createdDate === 'string' && item.createdDate.includes('T')) {
|
|
224
|
-
eventDate = parse(item.createdDate, "yyyy-MM-dd'T'HH:mm:ss'Z'", new Date());
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
eventDate = fromUnixTime(item.createdDate / 1000);
|
|
228
|
-
}
|
|
88
|
+
const eventDate = parseISO(item.createdDate);
|
|
229
89
|
const currentDate = format(eventDate, 'MMMM d, yyyy');
|
|
90
|
+
// Show avatar + date header when: (1) first item, (2) user changed from
|
|
91
|
+
// previous event, or (3) calendar date changed. After any list mutation
|
|
92
|
+
// (filter, sort, paginate) applyAvatarLogic must be re-run so boundaries
|
|
93
|
+
// remain correct.
|
|
230
94
|
const useAvatar = index === 0 ||
|
|
231
|
-
(
|
|
232
|
-
(
|
|
95
|
+
(previousUser !== null && currentUser !== previousUser) ||
|
|
96
|
+
(previousDate !== null && currentDate !== previousDate);
|
|
233
97
|
previousUser = currentUser;
|
|
234
98
|
previousDate = currentDate;
|
|
235
|
-
const user = item.createdByCustomer
|
|
236
|
-
? item.createdByCustomer
|
|
237
|
-
? 'customer'
|
|
238
|
-
: 'internal'
|
|
239
|
-
: currentUser === 'Case Diagnostics' || currentUser === 'GSS Tools'
|
|
240
|
-
? 'internal'
|
|
241
|
-
: 'customer';
|
|
99
|
+
const user = item.createdByCustomer ? 'customer' : 'internal';
|
|
242
100
|
const leftEvent = {
|
|
243
101
|
date: currentDate,
|
|
244
102
|
text: format(eventDate, 'h:mm a zzz'),
|
|
@@ -247,11 +105,8 @@ const transformApiResponseToTimelineData = (apiResponse) => {
|
|
|
247
105
|
if (item.type === 'Change') {
|
|
248
106
|
outputText = applyReplacements(item);
|
|
249
107
|
}
|
|
250
|
-
else {
|
|
251
|
-
outputText = stripHTML(outputText);
|
|
252
|
-
}
|
|
253
108
|
const rightEvent = {
|
|
254
|
-
date: `${item.createdByUserName} ${outputText}
|
|
109
|
+
date: item.createdByUserName ? `${item.createdByUserName} ${outputText}` : outputText,
|
|
255
110
|
text: '',
|
|
256
111
|
user: user,
|
|
257
112
|
useAvatar: useAvatar,
|
|
@@ -259,27 +114,24 @@ const transformApiResponseToTimelineData = (apiResponse) => {
|
|
|
259
114
|
return {
|
|
260
115
|
left: leftEvent,
|
|
261
116
|
right: rightEvent,
|
|
117
|
+
photoUrl: item.photoUrl,
|
|
118
|
+
userName: currentUser,
|
|
262
119
|
};
|
|
263
120
|
});
|
|
264
121
|
return timelineEvents;
|
|
265
122
|
};
|
|
266
|
-
|
|
267
|
-
const anchorTagRegex = /<a[^>]*>(.*?)<\/a>/g;
|
|
268
|
-
// We are trying to return the text without having the info in the anchor.
|
|
269
|
-
return htmlString.replace(anchorTagRegex, '');
|
|
270
|
-
}
|
|
271
|
-
const Timeline = ({ caseNumber }) => {
|
|
123
|
+
const Timeline = ({ caseNumber, sfdcCaseId }) => {
|
|
272
124
|
const { t } = useTranslation();
|
|
273
125
|
const [timelineEvents, setTimelineEvents] = useState([]);
|
|
274
126
|
const [originalTimelineEvents, setOriginalTimelineEvents] = useState([]);
|
|
275
|
-
const [isFetchingData, setIsFetchingData] = useState();
|
|
276
127
|
const lastNodeRef = useRef(null);
|
|
128
|
+
const { historyItems, loading: isFetchingData, error } = useCaseHistory(sfdcCaseId);
|
|
129
|
+
const fetchError = error ? t('Unable to connect') : null;
|
|
277
130
|
const [dateValue, setDateValue] = useState('');
|
|
278
131
|
const [searchValue, setSearchValue] = useState('');
|
|
279
132
|
const [filteredEvents, setFilteredEvents] = useState([]);
|
|
280
133
|
const [isSelectOpen, setIsSelectOpen] = useState(false);
|
|
281
134
|
const [selectedOrder, setSelectedOrder] = useState('Newest to Oldest');
|
|
282
|
-
const [fetchError, setFetchError] = useState(null);
|
|
283
135
|
const [page, setPage] = useState(1);
|
|
284
136
|
const [perPage, setPerPage] = useState(20);
|
|
285
137
|
const onSetPage = (_, newPage) => {
|
|
@@ -307,52 +159,34 @@ const Timeline = ({ caseNumber }) => {
|
|
|
307
159
|
}
|
|
308
160
|
setIsSelectOpen(false);
|
|
309
161
|
};
|
|
162
|
+
// "Newest to Oldest" is the native API order (SF returns history newest-first).
|
|
163
|
+
// "Oldest to Newest" reverses it. Avatar logic must be reapplied after reorder.
|
|
310
164
|
const reorderTimelineEvents = (order) => {
|
|
311
165
|
const events = order === 'Newest to Oldest' ? [...originalTimelineEvents] : [...originalTimelineEvents].reverse();
|
|
312
166
|
setTimelineEvents(applyAvatarLogic(events));
|
|
313
167
|
};
|
|
168
|
+
// Re-derives avatar/date-header boundaries after list mutations (filter, sort, paginate).
|
|
314
169
|
const applyAvatarLogic = (events) => {
|
|
315
170
|
let previousUser = null;
|
|
316
171
|
let previousDate = null;
|
|
317
172
|
return events.map((event, index) => {
|
|
318
|
-
const currentUser = event.
|
|
173
|
+
const currentUser = event.userName || '';
|
|
319
174
|
const currentDate = event.left.date;
|
|
320
175
|
const useAvatar = index === 0 ||
|
|
321
|
-
(
|
|
322
|
-
(
|
|
176
|
+
(previousUser !== null && currentUser !== previousUser) ||
|
|
177
|
+
(previousDate !== null && currentDate !== previousDate);
|
|
323
178
|
previousUser = currentUser;
|
|
324
179
|
previousDate = currentDate;
|
|
325
180
|
return Object.assign(Object.assign({}, event), { right: Object.assign(Object.assign({}, event.right), { useAvatar: useAvatar }) });
|
|
326
181
|
});
|
|
327
182
|
};
|
|
328
183
|
useEffect(() => {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const options = {
|
|
334
|
-
sortField: 'createdDate',
|
|
335
|
-
sortOrder: 'DESC',
|
|
336
|
-
showVerbose: true,
|
|
337
|
-
};
|
|
338
|
-
try {
|
|
339
|
-
const response = yield caseHistory.getHistoryv1(caseNumber, options);
|
|
340
|
-
const transformedData = transformApiResponseToTimelineData(response);
|
|
341
|
-
setTimelineEvents(transformedData);
|
|
342
|
-
setOriginalTimelineEvents(transformedData);
|
|
343
|
-
}
|
|
344
|
-
catch (error) {
|
|
345
|
-
console.error('Failed to fetch history:', error);
|
|
346
|
-
setFetchError(t('Unable to connect'));
|
|
347
|
-
}
|
|
348
|
-
finally {
|
|
349
|
-
setIsFetchingData(false);
|
|
350
|
-
}
|
|
351
|
-
});
|
|
184
|
+
if (historyItems.length > 0) {
|
|
185
|
+
const transformedData = transformApiResponseToTimelineData({ historyItems });
|
|
186
|
+
setTimelineEvents(transformedData);
|
|
187
|
+
setOriginalTimelineEvents(transformedData);
|
|
352
188
|
}
|
|
353
|
-
|
|
354
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
355
|
-
}, [caseNumber]);
|
|
189
|
+
}, [historyItems]);
|
|
356
190
|
const futureDateValidator = (date) => {
|
|
357
191
|
const today = new Date();
|
|
358
192
|
today.setHours(0, 0, 0, 0); // Normalize to midnight
|
|
@@ -361,6 +195,9 @@ const Timeline = ({ caseNumber }) => {
|
|
|
361
195
|
}
|
|
362
196
|
return '';
|
|
363
197
|
};
|
|
198
|
+
// Measures the DOM to shorten the vertical timeline connector line so it does not
|
|
199
|
+
// extend past the last node. Sets the --timeline-bottom CSS variable, recomputed
|
|
200
|
+
// on resize and list changes via requestAnimationFrame.
|
|
364
201
|
const updateLineStyle = () => {
|
|
365
202
|
const timelineElement = document.querySelector('.timeline');
|
|
366
203
|
if (timelineElement) {
|
|
@@ -395,7 +232,10 @@ const Timeline = ({ caseNumber }) => {
|
|
|
395
232
|
timelineElement.style.setProperty('--timeline-bottom', '0px');
|
|
396
233
|
}
|
|
397
234
|
}
|
|
398
|
-
return () =>
|
|
235
|
+
return () => {
|
|
236
|
+
debouncedUpdateLineStyle.cancel();
|
|
237
|
+
window.removeEventListener('resize', debouncedUpdateLineStyle);
|
|
238
|
+
};
|
|
399
239
|
}, [isFetchingData, filteredEvents, page, perPage]);
|
|
400
240
|
const handleSearchChange = (_, value) => {
|
|
401
241
|
setSearchValue(value.trim());
|
|
@@ -434,7 +274,6 @@ const Timeline = ({ caseNumber }) => {
|
|
|
434
274
|
}, [searchValue, dateValue, timelineEvents]);
|
|
435
275
|
const handleReload = (e) => {
|
|
436
276
|
e.preventDefault();
|
|
437
|
-
window.location.href = window.location.href;
|
|
438
277
|
window.location.reload();
|
|
439
278
|
};
|
|
440
279
|
const renderTimelineContent = () => {
|
|
@@ -452,7 +291,7 @@ const Timeline = ({ caseNumber }) => {
|
|
|
452
291
|
React.createElement(Trans, null, "Try modifying your search query or changing the date range and try again."))));
|
|
453
292
|
}
|
|
454
293
|
const paginatedEvents = filteredEvents.slice((page - 1) * perPage, page * perPage);
|
|
455
|
-
return (React.createElement(React.Fragment, null, paginatedEvents.map((node, index) => (React.createElement(TimelineNode, { key: index, leftEvent: node.left, rightEvent: node.right, user: node.right.user, useAvatar: node.right.useAvatar, searchValue: searchValue, highlightDate: !!dateValue, ref: index === paginatedEvents.length - 1 ? lastNodeRef : null })))));
|
|
294
|
+
return (React.createElement(React.Fragment, null, paginatedEvents.map((node, index) => (React.createElement(TimelineNode, { key: index, leftEvent: node.left, rightEvent: node.right, user: node.right.user, useAvatar: node.right.useAvatar, photoUrl: node.photoUrl, searchValue: searchValue, highlightDate: !!dateValue, ref: index === paginatedEvents.length - 1 ? lastNodeRef : null })))));
|
|
456
295
|
};
|
|
457
296
|
return (React.createElement(React.Fragment, null,
|
|
458
297
|
React.createElement("div", { className: "timelineMenu" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CaseSummary.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseSummary/CaseSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC;AAuB3B,OAAO,KAA0C,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"CaseSummary.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseSummary/CaseSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC;AAuB3B,OAAO,KAA0C,MAAM,OAAO,CAAC;AAQ/D,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,sBA8LxC,CAAC"}
|
|
@@ -22,6 +22,7 @@ import React, { useContext, useEffect, useState } from 'react';
|
|
|
22
22
|
import { Trans } from 'react-i18next';
|
|
23
23
|
import { CaseSummaryStates } from '../../../../constants/caseDetailsConstants';
|
|
24
24
|
import { useCaseSelector } from '../../../../context/CaseContext';
|
|
25
|
+
import { useCaseComments } from '../../../../hooks/useCaseComments';
|
|
25
26
|
import { CaseSummaryErrorMessage } from './CaseSummaryErrorMessage';
|
|
26
27
|
export const CaseSummary = (props) => {
|
|
27
28
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -29,10 +30,14 @@ export const CaseSummary = (props) => {
|
|
|
29
30
|
const [caseSummaryData, setCaseSummaryData] = useState(getApiResourceObject(null, true));
|
|
30
31
|
const [caseSummaryState, setCaseSummaryState] = useState();
|
|
31
32
|
const [errorMessage, setErrorMessage] = useState('');
|
|
32
|
-
const {
|
|
33
|
-
caseComments: state.caseDetails.comments,
|
|
33
|
+
const { caseLanguage, caseSalesforceId } = useCaseSelector((state) => ({
|
|
34
34
|
caseLanguage: state.caseDetails.caseLanguage,
|
|
35
|
+
caseSalesforceId: state.caseDetails.id,
|
|
35
36
|
}), isEqual);
|
|
37
|
+
const { comments: caseComments } = useCaseComments({
|
|
38
|
+
caseId: caseSalesforceId,
|
|
39
|
+
skip: !caseSalesforceId,
|
|
40
|
+
});
|
|
36
41
|
const { globalMetadataState: { loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
|
|
37
42
|
const isInternal = (_b = (_a = loggedInUserRights === null || loggedInUserRights === void 0 ? void 0 : loggedInUserRights.data) === null || _a === void 0 ? void 0 : _a.isInternal) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
38
43
|
const onCloseFeedbackModal = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RMEEscalationList.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/RMEEscalations/RMEEscalationList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAqB,MAAM,2CAA2C,CAAC;AAe/F,OAAO,KAAsC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RMEEscalationList.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/RMEEscalations/RMEEscalationList.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAqB,MAAM,2CAA2C,CAAC;AAe/F,OAAO,KAAsC,MAAM,OAAO,CAAC;AAU3D,UAAU,MAAM;IACZ,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACtB;AAOD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,KAAK,EAAE,MAAM,qBAkMtD"}
|
|
@@ -19,11 +19,10 @@ import isEqual from 'lodash/isEqual';
|
|
|
19
19
|
import React, { useEffect, useRef, useState } from 'react';
|
|
20
20
|
import { Trans, useTranslation } from 'react-i18next';
|
|
21
21
|
import { useCaseDispatch, useCaseSelector } from '../../../../context/CaseContext';
|
|
22
|
-
import { useCaseDetailsPageDispatchContext
|
|
23
|
-
import {
|
|
22
|
+
import { useCaseDetailsPageDispatchContext } from '../../../../context/CaseDetailsPageContext';
|
|
23
|
+
import { GET_CASE_COMMENTS } from '../../../../hooks/useCaseComments';
|
|
24
24
|
import { escalationStatus } from '../../../../models/escalation';
|
|
25
25
|
import { fetchCaseEscalations } from '../../../../reducers/CaseDetailsPageReducer';
|
|
26
|
-
import { updateDiscussionStateComments } from '../../../../reducers/CaseDiscussionTabReducer';
|
|
27
26
|
import { checkForCaseStatusToggleOnAttachOrComment } from '../../../../reducers/CaseReducer';
|
|
28
27
|
const ESCALATION_MSG = 'Request Management Escalation:';
|
|
29
28
|
const UPDATE_ESCALATION_MSG = 'Escalation update requested. You will receive an update from a manager shortly.';
|
|
@@ -39,9 +38,7 @@ export default function RMEEscalationList(props) {
|
|
|
39
38
|
const { request: updateCaseRequest, isFetching: isUpdatingCase } = useFetch(publicApi.kase.updateCase, {
|
|
40
39
|
propgateErrors: true,
|
|
41
40
|
});
|
|
42
|
-
const
|
|
43
|
-
const dispatchDiscussion = useCaseDiscussionTabDispatchContext();
|
|
44
|
-
const { caseDetailsPageState: { caseFeedbacksHydra }, } = useCaseDetailsPageStateContext();
|
|
41
|
+
const client = useApolloClient();
|
|
45
42
|
const caseDetailsPageDispatch = useCaseDetailsPageDispatchContext();
|
|
46
43
|
const escalationUpdateInProgessIds = useRef([]);
|
|
47
44
|
const caseDispatch = useCaseDispatch();
|
|
@@ -69,7 +66,7 @@ export default function RMEEscalationList(props) {
|
|
|
69
66
|
commentBody: comment,
|
|
70
67
|
contentType: 'plaintext',
|
|
71
68
|
});
|
|
72
|
-
|
|
69
|
+
client.refetchQueries({ include: [GET_CASE_COMMENTS] });
|
|
73
70
|
yield updateCaseRequest(props.caseNumber, { customerEscalation: true });
|
|
74
71
|
checkForCaseStatusToggleOnAttachOrComment(caseDispatch, props.isInternal, props.caseStatus);
|
|
75
72
|
escalationNum && ToastNotification.addSuccessMessage(message);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Cep.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseManagement/Cep.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Cep.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseManagement/Cep.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAe/D,UAAU,MAAM;CAAG;AAEnB,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,qBAkThC"}
|
|
@@ -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 { useApolloClient } from '@apollo/client/react';
|
|
10
11
|
import { Button, Checkbox, Form, FormGroup, FormHelperText, HelperText, HelperTextItem, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, Popover, PopoverPosition, TextArea, TextInput, ValidatedOptions, } from '@patternfly/react-core';
|
|
11
12
|
import QuestionCircleIcon from '@patternfly/react-icons/dist/js/icons/question-circle-icon';
|
|
12
13
|
import { LoadingIndicator, ToastNotification, useConfirmation } from '@rh-support/components';
|
|
@@ -17,10 +18,8 @@ import isEqual from 'lodash/isEqual';
|
|
|
17
18
|
import React, { useContext, useEffect, useState } from 'react';
|
|
18
19
|
import { Trans, useTranslation } from 'react-i18next';
|
|
19
20
|
import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
|
|
20
|
-
import {
|
|
21
|
-
import { useCaseDiscussionTabDispatchContext, useCaseDiscussionTabStateContext, } from '../../context/CaseDiscussionTabContext';
|
|
21
|
+
import { GET_CASE_COMMENTS } from '../../hooks/useCaseComments';
|
|
22
22
|
import { useCaseUpdateErrorMessage } from '../../hooks/useCaseUpdateErrorMessage';
|
|
23
|
-
import { updateDiscussionStateComments } from '../../reducers/CaseDiscussionTabReducer';
|
|
24
23
|
import { checkForCaseStatusToggleOnAttachOrComment, postCepDetails, setCaseDetails, setCaseState, updateCaseDetails, } from '../../reducers/CaseReducer';
|
|
25
24
|
import { PDFContext } from '../CaseEditView/PDFContainer';
|
|
26
25
|
export function Cep(props) {
|
|
@@ -42,9 +41,7 @@ export function Cep(props) {
|
|
|
42
41
|
const ability = useContext(AbilityContext);
|
|
43
42
|
const canUseCep = ability.can(resourceActions.PATCH, resources.CASE_CREATE, CaseListFields.CEP);
|
|
44
43
|
const confirm = useConfirmation();
|
|
45
|
-
const
|
|
46
|
-
const { sort, allDiscussions, discussionFiltersListState } = useCaseDiscussionTabStateContext();
|
|
47
|
-
const { caseDetailsPageState: { caseFeedbacksHydra }, } = useCaseDetailsPageStateContext();
|
|
44
|
+
const client = useApolloClient();
|
|
48
45
|
const canEditCase = useCanEditCase();
|
|
49
46
|
const [saveButtonIsClicked, setSaveButtonIsClicked] = useState(false);
|
|
50
47
|
const { isExportingPDF } = useContext(PDFContext);
|
|
@@ -92,7 +89,7 @@ export function Cep(props) {
|
|
|
92
89
|
checkForCaseStatusToggleOnAttachOrComment(caseDispatch, loggedInUserRights.data.isInternal(), status);
|
|
93
90
|
if (caseDetails.cep) {
|
|
94
91
|
yield postCepDetails(caseDispatch, caseNumber, cepDetailsLocal);
|
|
95
|
-
|
|
92
|
+
client.refetchQueries({ include: [GET_CASE_COMMENTS] });
|
|
96
93
|
}
|
|
97
94
|
ToastNotification.addSuccessMessage(t(`Consultant Engagement in Progress has been updated successfully`));
|
|
98
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NewProductVersionSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ProductSelector/NewProductVersionSelector.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NewProductVersionSelector.d.ts","sourceRoot":"","sources":["../../../../src/components/ProductSelector/NewProductVersionSelector.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAOxE,UAAU,MAAM;IACZ,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,qCAAqC,EAAE,OAAO,CAAC;CAClD;AAED,eAAO,MAAM,yBAAyB,GAAI,OAAO,MAAM,sBAgGtD,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useApolloClient } from '@apollo/client/react';
|
|
2
2
|
import { SingleSelectDropdown } from '@rh-support/components';
|
|
3
3
|
import { GlobalMetadataStateContext } from '@rh-support/react-context';
|
|
4
|
+
import { getUniqueSortedVersions } from '@rh-support/utils';
|
|
4
5
|
import isEmpty from 'lodash/isEmpty';
|
|
5
6
|
import isEqual from 'lodash/isEqual';
|
|
6
|
-
import React, { useContext, useEffect, useState } from 'react';
|
|
7
|
+
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
|
7
8
|
import { useTranslation } from 'react-i18next';
|
|
8
9
|
import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
|
|
9
10
|
import { getVersionsDetails, setCaseState } from '../../reducers/CaseReducer';
|
|
@@ -42,6 +43,19 @@ export const NewProductVersionSelector = (props) => {
|
|
|
42
43
|
}
|
|
43
44
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
44
45
|
}, [versionsDetails.data]);
|
|
46
|
+
const sortedVersionNames = useMemo(() => {
|
|
47
|
+
var _a;
|
|
48
|
+
if (!((_a = versionsDetails.data) === null || _a === void 0 ? void 0 : _a.length))
|
|
49
|
+
return [];
|
|
50
|
+
const versionNames = versionsDetails.data.map((v) => v.name);
|
|
51
|
+
const productObj = getProductObj(allProducts.data.productsResult, product);
|
|
52
|
+
if (productObj === null || productObj === void 0 ? void 0 : productObj.hasComponentsInsteadOfVersions) {
|
|
53
|
+
return [...versionNames].sort();
|
|
54
|
+
}
|
|
55
|
+
const numeric = versionNames.filter((v) => /^\d/.test(v));
|
|
56
|
+
const alpha = versionNames.filter((v) => !/^\d/.test(v));
|
|
57
|
+
return [...getUniqueSortedVersions(numeric), ...alpha.sort()];
|
|
58
|
+
}, [versionsDetails.data, allProducts.data.productsResult, product]);
|
|
45
59
|
const onSelect = (selectedOption) => {
|
|
46
60
|
const selection = selectedOption.value;
|
|
47
61
|
if (isEqual(selection, version)) {
|
|
@@ -57,9 +71,9 @@ export const NewProductVersionSelector = (props) => {
|
|
|
57
71
|
label: version || '',
|
|
58
72
|
value: version || '',
|
|
59
73
|
});
|
|
60
|
-
const getDropdownOptions = () =>
|
|
61
|
-
label:
|
|
62
|
-
value:
|
|
74
|
+
const getDropdownOptions = () => sortedVersionNames.map((versionOption) => ({
|
|
75
|
+
label: versionOption,
|
|
76
|
+
value: versionOption,
|
|
63
77
|
}));
|
|
64
78
|
return (React.createElement(SingleSelectDropdown, { onSelect: onSelect, selected: getSelectedOption(), options: getDropdownOptions(), placeholder: t('Select a version'), ariaLabel: t('Select a version'), isInvalid: isEmpty(version) && showValidationLocal, isDisabled: isEmpty(product) || allProducts.isFetching, dataTrackingId: "get-support-version-dropdown-selector", isLoading: versionsDetails.isFetching }));
|
|
65
79
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpdateSeverityModal.d.ts","sourceRoot":"","sources":["../../../../src/components/UpdateSeverityModal/UpdateSeverityModal.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAmE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"UpdateSeverityModal.d.ts","sourceRoot":"","sources":["../../../../src/components/UpdateSeverityModal/UpdateSeverityModal.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAmE,MAAM,OAAO,CAAC;AAWxF,UAAU,MAAM;IACZ,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,KAAK,EAAE,MAAM,qBAykBxD"}
|
|
@@ -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 { useApolloClient } from '@apollo/client/react';
|
|
10
11
|
import { publicApi } from '@cee-eng/hydrajs';
|
|
11
12
|
import { Button, Dropdown, DropdownItem, DropdownList, Flex, FlexItem, MenuToggle, Modal, ModalBody, ModalFooter, ModalHeader, Spinner, TextArea, } from '@patternfly/react-core';
|
|
12
13
|
import { ToastNotification, useFetch } from '@rh-support/components';
|
|
@@ -21,10 +22,8 @@ import map from 'lodash/map';
|
|
|
21
22
|
import React, { useContext, useEffect, useReducer, useRef, useState } from 'react';
|
|
22
23
|
import { Trans, useTranslation } from 'react-i18next';
|
|
23
24
|
import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
|
|
24
|
-
import {
|
|
25
|
-
import { useCaseDiscussionTabDispatchContext, useCaseDiscussionTabStateContext, } from '../../context/CaseDiscussionTabContext';
|
|
25
|
+
import { GET_CASE_COMMENTS } from '../../hooks/useCaseComments';
|
|
26
26
|
import { useCaseUpdateErrorMessage } from '../../hooks/useCaseUpdateErrorMessage';
|
|
27
|
-
import { updateDiscussionStateComments } from '../../reducers/CaseDiscussionTabReducer';
|
|
28
27
|
import { getNewSeverityStringDef, getSeverityDescription } from '../../reducers/CaseHelpers';
|
|
29
28
|
import { caseOverviewReducer, initialCaseViewState, setSeverityUpdating } from '../../reducers/CaseOverviewReducer';
|
|
30
29
|
import { checkForCaseStatusToggleOnAttachOrComment, setCaseState, updateCaseDetails } from '../../reducers/CaseReducer';
|
|
@@ -40,12 +39,10 @@ export default function UpdateSeverityModal(props) {
|
|
|
40
39
|
const [isUpdateClickedToShowError, setIsUpdateClickedToShowError] = useState(false);
|
|
41
40
|
const [isSeverityInValid, setIsSeverityInValid] = useState(false);
|
|
42
41
|
const [seviritiesOptions, setSeveritiesOptions] = useState([]);
|
|
42
|
+
const client = useApolloClient();
|
|
43
43
|
const { request: postCommentRequest, isFetching: isPostingComment } = useFetch(publicApi.kase.postComment, {
|
|
44
44
|
propgateErrors: true,
|
|
45
45
|
});
|
|
46
|
-
const { caseDetailsPageState: { caseFeedbacksHydra }, } = useCaseDetailsPageStateContext();
|
|
47
|
-
const dispatchDiscussion = useCaseDiscussionTabDispatchContext();
|
|
48
|
-
const { sort, allDiscussions, discussionFiltersListState } = useCaseDiscussionTabStateContext();
|
|
49
46
|
const { globalMetadataState: { allCaseSeverities, allProducts, loggedInUserRights }, } = useContext(GlobalMetadataStateContext);
|
|
50
47
|
const caseState = useCaseSelector((state) => ({
|
|
51
48
|
caseDetails: {
|
|
@@ -247,7 +244,7 @@ export default function UpdateSeverityModal(props) {
|
|
|
247
244
|
setDescriptionValue(descriptionValue === null || descriptionValue === void 0 ? void 0 : descriptionValue.trim());
|
|
248
245
|
}
|
|
249
246
|
finally {
|
|
250
|
-
yield
|
|
247
|
+
yield client.refetchQueries({ include: [GET_CASE_COMMENTS] });
|
|
251
248
|
setIsUpdateClickedToShowError(false);
|
|
252
249
|
setDescriptionValue('');
|
|
253
250
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePostComment.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/usePostComment.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePostComment.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/usePostComment.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAK9E,wBAAgB,cAAc,CAAC,EAAE,UAAU,EAAE;;CAAA;2FAWtC,IAAI,CAAC,mBAAmB,EAAE,aAAa,GAAG,aAAa,GAAG,mBAAmB,CAAC,GAAG;QAChF,qBAAqB,EAAE,OAAO,CAAC;KAClC;;EAiBJ"}
|