@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
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const getLocaleNameFromLocalCode = (localeCode) => {
|
|
2
|
+
if ('Intl' in window && 'DisplayNames' in Intl) {
|
|
3
|
+
try {
|
|
4
|
+
const [lang, locale] = localeCode.includes('_') ? localeCode.split('_') : localeCode.split('-');
|
|
5
|
+
// https://github.com/microsoft/TypeScript/issues/41338
|
|
6
|
+
const langName = new Intl.DisplayNames([lang], { type: 'language' });
|
|
7
|
+
const regionNamesInLang = new Intl.DisplayNames([lang], { type: 'region' });
|
|
8
|
+
return `${regionNamesInLang.of(locale)} (${langName.of(lang)})`;
|
|
9
|
+
}
|
|
10
|
+
catch (e) {
|
|
11
|
+
return localeCode;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return localeCode;
|
|
15
|
+
};
|
|
16
|
+
export const formatSessionLinks = (sessionLink) => {
|
|
17
|
+
const links = sessionLink
|
|
18
|
+
.split(/[;,| \n\r\t]+/)
|
|
19
|
+
.map((link) => link.trim())
|
|
20
|
+
.filter(Boolean);
|
|
21
|
+
return links.map((link) => `[${link}](${link})`).join('\n');
|
|
22
|
+
};
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ICaseComment } from '@cee-eng/hydrajs/@types/api/public/case';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
interface IProps {
|
|
4
4
|
caseNumber: string;
|
|
5
5
|
caseComments: ICaseComment[];
|
|
6
|
-
|
|
6
|
+
commentsLoading?: boolean;
|
|
7
|
+
commentsError?: unknown;
|
|
7
8
|
accountNumber: string;
|
|
8
9
|
tabRef: React.MutableRefObject<HTMLDivElement>;
|
|
9
10
|
isDiscussionTab: boolean;
|
|
11
|
+
refetchComments: () => Promise<unknown> | void;
|
|
10
12
|
}
|
|
11
13
|
export default function CaseDiscussion(props: IProps): React.JSX.Element;
|
|
12
14
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CaseDiscussion.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CaseDiscussion.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAcvE,OAAO,KAAoE,MAAM,OAAO,CAAC;AAwCzF,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,qBAmhBnD"}
|
|
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
// TODO: Re-enable after GraphQL migration of chats, external trackers, attachments
|
|
11
|
+
// import { ICaseChat, IExternalTrackerUpdate } from '@cee-eng/hydrajs/@types/api/public/case';
|
|
12
|
+
// import { IAttachment } from '@cee-eng/hydrajs/@types/models/attachment';
|
|
11
13
|
import { MenuToggle, Select, SelectList, SelectOption } from '@patternfly/react-core';
|
|
12
|
-
import { AlertMessage, AlertType, ErrorBoundary, LoadingIndicator
|
|
14
|
+
import { AlertMessage, AlertType, ErrorBoundary, LoadingIndicator } from '@rh-support/components';
|
|
13
15
|
import { useGlobalStateContext } from '@rh-support/react-context';
|
|
14
|
-
import {
|
|
15
|
-
import { dtmTrackEventCaseStepEncountered, getDropdownBtnPlaceholder, getUrlParsedParams, scrollIntoView, } from '@rh-support/utils';
|
|
16
|
+
import { dtmTrackEventCaseStepEncountered, getUrlParsedParams, scrollIntoView } from '@rh-support/utils';
|
|
16
17
|
import cloneDeep from 'lodash/cloneDeep';
|
|
17
18
|
import filter from 'lodash/filter';
|
|
18
19
|
import findIndex from 'lodash/findIndex';
|
|
@@ -24,18 +25,27 @@ import { Trans, useTranslation } from 'react-i18next';
|
|
|
24
25
|
import { useLocation } from 'react-router-dom';
|
|
25
26
|
import { AutoSizer, CellMeasurer, CellMeasurerCache, List, WindowScroller } from 'react-virtualized';
|
|
26
27
|
import { useCaseDispatch, useCaseSelector } from '../../../../context/CaseContext';
|
|
27
|
-
import { useCaseDetailsPageDispatchContext, useCaseDetailsPageStateContext, } from '../../../../context/CaseDetailsPageContext';
|
|
28
28
|
import { useCaseDiscussionTabDispatchContext, useCaseDiscussionTabStateContext, } from '../../../../context/CaseDiscussionTabContext';
|
|
29
|
-
import { clearReplyComment, discussionSortOrderConst, DiscussionType, setCommentText, setDiscussions,
|
|
29
|
+
import { clearReplyComment, discussionSortOrderConst, DiscussionType, setCommentText, setDiscussions, setSort,
|
|
30
|
+
// TODO: Re-enable after GraphQL migration
|
|
31
|
+
// setFilter,
|
|
32
|
+
// updateAttachment,
|
|
33
|
+
// updateAttacmentsAfterRemoval,
|
|
34
|
+
// updateCommentStateFeedback,
|
|
35
|
+
// updateDiscussionStateAttachments,
|
|
36
|
+
} from '../../../../reducers/CaseDiscussionTabReducer';
|
|
30
37
|
import { setCaseState } from '../../../../reducers/CaseReducer';
|
|
31
|
-
|
|
38
|
+
// TODO: Re-enable after GraphQL migration of attachments
|
|
39
|
+
// import { AttachmentContextProvider } from '../../../shared/fileUpload/reducer/AttachmentReducerContext';
|
|
32
40
|
import { PDFContext } from '../../PDFContainer';
|
|
33
|
-
|
|
34
|
-
import
|
|
41
|
+
// TODO: Re-enable after GraphQL migration
|
|
42
|
+
// import CaseAttachment from './CaseAttachment';
|
|
43
|
+
// import CaseChat from './CaseChat';
|
|
35
44
|
import CaseComments from './CaseComments';
|
|
36
|
-
import CaseExternalTrackerUpdate from './CaseExternalTrackerUpdate';
|
|
45
|
+
// import CaseExternalTrackerUpdate from './CaseExternalTrackerUpdate';
|
|
37
46
|
import { CommentSearch } from './CommentSearch';
|
|
38
47
|
import { PostComment } from './PostComment';
|
|
48
|
+
/** Threshold above which comments render in a virtualized (windowed) list for performance. */
|
|
39
49
|
const VC_MINIMUM_COMMENT = 150;
|
|
40
50
|
let cellMeasureCache = new CellMeasurerCache({
|
|
41
51
|
fixedWidth: true,
|
|
@@ -43,30 +53,20 @@ let cellMeasureCache = new CellMeasurerCache({
|
|
|
43
53
|
});
|
|
44
54
|
export default function CaseDiscussion(props) {
|
|
45
55
|
const { t } = useTranslation();
|
|
46
|
-
const { isPostingRemoteRequestCommentCompleted,
|
|
56
|
+
const { isPostingRemoteRequestCommentCompleted, product, version } = useCaseSelector((state) => ({
|
|
47
57
|
isPostingRemoteRequestCommentCompleted: state.isPostingRemoteRequestCommentCompleted,
|
|
48
|
-
screenSessionRequested: state.caseDetails.screenSessionRequested,
|
|
49
58
|
product: state.caseDetails.product,
|
|
50
59
|
version: state.caseDetails.version,
|
|
51
60
|
}), isEqual);
|
|
52
61
|
const urlSearchParams = getUrlParsedParams(useLocation().search);
|
|
53
|
-
const discussionIdFromUrl =
|
|
54
|
-
(urlSearchParams === null || urlSearchParams === void 0 ? void 0 : urlSearchParams.externalTrackerId) ||
|
|
55
|
-
(urlSearchParams === null || urlSearchParams === void 0 ? void 0 : urlSearchParams.attachmentId) ||
|
|
56
|
-
(urlSearchParams === null || urlSearchParams === void 0 ? void 0 : urlSearchParams.chatId));
|
|
62
|
+
const discussionIdFromUrl = urlSearchParams === null || urlSearchParams === void 0 ? void 0 : urlSearchParams.commentId;
|
|
57
63
|
const activeDiscussionElementRef = useRef(null);
|
|
58
|
-
const { sort,
|
|
59
|
-
const { globalMetadataState: {
|
|
64
|
+
const { sort, allDiscussions, replyCommentText, replyCommentCreator } = useCaseDiscussionTabStateContext();
|
|
65
|
+
const { globalMetadataState: { navBarRef }, } = useGlobalStateContext();
|
|
60
66
|
const dispatchDiscussion = useCaseDiscussionTabDispatchContext();
|
|
61
67
|
const caseDispatch = useCaseDispatch();
|
|
62
|
-
const { caseDetailsPageState: { caseFeedbacksHydra, caseAttachmentHydra, caseExternalTrackersUpdate }, } = useCaseDetailsPageStateContext();
|
|
63
|
-
const dispatchCaseDetailsHydraAttachments = useCaseDetailsPageDispatchContext();
|
|
64
68
|
const { caseNumber } = props;
|
|
65
69
|
const activeElementId = useRef(null);
|
|
66
|
-
const ability = useContext(AbilityContext);
|
|
67
|
-
const canSeeExternalTracker = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_EXTERNAL_TRACKER);
|
|
68
|
-
const canSeeChat = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_CHAT);
|
|
69
|
-
const canSeeAttachments = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_SEE_ATTACHMENTS);
|
|
70
70
|
const listRef = React.useRef(null);
|
|
71
71
|
const windowScrollerRef = React.useRef(null);
|
|
72
72
|
const commentRef = React.useRef(null);
|
|
@@ -78,10 +78,7 @@ export default function CaseDiscussion(props) {
|
|
|
78
78
|
const [isJumpToCommentClicked, setJumpToCommentClicked] = useState(false);
|
|
79
79
|
const [canUpdateScrollTop, setCanUpdateScrollTop] = useState(true);
|
|
80
80
|
const [replyingToPrivateComment, setReplyingToPrivateComment] = useState(null);
|
|
81
|
-
// used for tracking comment section width changes
|
|
82
81
|
const [discussionSectionWidth, setDiscussionSectionWidth] = useState(null);
|
|
83
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
84
|
-
const [selectedFilterItems, setSelectedFilterItems] = useState([]);
|
|
85
82
|
const [isSortOpen, setIsSortOpen] = useState(false);
|
|
86
83
|
const [sortSelected, setSortSelected] = useState('Select a value');
|
|
87
84
|
if (props.isDiscussionTab) {
|
|
@@ -90,18 +87,10 @@ export default function CaseDiscussion(props) {
|
|
|
90
87
|
defaultHeight: 100,
|
|
91
88
|
});
|
|
92
89
|
}
|
|
93
|
-
const computeFilterComment = () => {
|
|
94
|
-
return filter(allDiscussions, (discussion) => {
|
|
95
|
-
const activeFilter = discussionFiltersListState.filter((filter) => filter.value === discussion.discussionType && filter.isSelected);
|
|
96
|
-
return activeFilter.length === 1 ? discussion : null;
|
|
97
|
-
});
|
|
98
|
-
};
|
|
99
90
|
const shouldRenderRVComponent = !isExportingPDF && allDiscussions.length > VC_MINIMUM_COMMENT;
|
|
100
|
-
// filter comments on the basis of filterBy and search api
|
|
101
|
-
const computeFilteredComments = computeFilterComment();
|
|
102
91
|
const comuteSearchedComments = searchResult.length === 0
|
|
103
|
-
? cloneDeep(
|
|
104
|
-
: filter([...
|
|
92
|
+
? cloneDeep(allDiscussions)
|
|
93
|
+
: filter([...allDiscussions], (o) => { var _a; return searchResult.indexOf((_a = o === null || o === void 0 ? void 0 : o.item) === null || _a === void 0 ? void 0 : _a.id) !== -1; });
|
|
105
94
|
const isSearchResultEmpty = !isEmpty(searchCommentText) && (searchResult.length === 0 || comuteSearchedComments.length === 0);
|
|
106
95
|
const setVRCommentIndex = (cId) => {
|
|
107
96
|
setCommentIndex(cId < 0 ? 0 : cId);
|
|
@@ -120,8 +109,6 @@ export default function CaseDiscussion(props) {
|
|
|
120
109
|
if (allDiscussions.length > VC_MINIMUM_COMMENT) {
|
|
121
110
|
const commentIndex = findIndex([...comuteSearchedComments], (discussion) => discussion.item.id === discussionIdFromUrl);
|
|
122
111
|
setVRCommentIndex(commentIndex);
|
|
123
|
-
// to fix scrolling to comment index when scrollTop value from window scroller is 0
|
|
124
|
-
// initial list items
|
|
125
112
|
if (0 <= commentIndex && commentIndex <= 3) {
|
|
126
113
|
const offset = 80;
|
|
127
114
|
const scrollTopValue = ((_a = windowScrollerRef === null || windowScrollerRef === void 0 ? void 0 : windowScrollerRef.current) === null || _a === void 0 ? void 0 : _a._positionFromTop) - offset;
|
|
@@ -146,38 +133,24 @@ export default function CaseDiscussion(props) {
|
|
|
146
133
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
147
134
|
}, [discussionIdFromUrl, allDiscussions, activeElementId.current]);
|
|
148
135
|
useEffect(() => {
|
|
149
|
-
if (!
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!caseFeedbacksHydra.isFetching && caseFeedbacksHydra.isError) {
|
|
156
|
-
console.log(`There was an error loading feedback.`);
|
|
157
|
-
}
|
|
158
|
-
// Attachments, feedbacks and external tracker updates apis are called in advance
|
|
159
|
-
if (!isExportingPDF &&
|
|
160
|
-
!caseAttachmentHydra.isFetching &&
|
|
161
|
-
!caseFeedbacksHydra.isFetching &&
|
|
162
|
-
!caseExternalTrackersUpdate.isFetching) {
|
|
163
|
-
setDiscussions(dispatchDiscussion, props.caseComments, props.caseChats, caseAttachmentHydra.data, caseFeedbacksHydra.data, caseExternalTrackersUpdate.data, discussionFiltersListState, canSeeExternalTracker, canSeeChat, canSeeAttachments);
|
|
136
|
+
if (!isExportingPDF) {
|
|
137
|
+
setDiscussions(dispatchDiscussion, props.caseComments, [], // TODO: Re-enable chats after GraphQL migration
|
|
138
|
+
[], // TODO: Re-enable attachments after GraphQL migration
|
|
139
|
+
[], // TODO: Re-enable feedbacks after GraphQL migration
|
|
140
|
+
[], // TODO: Re-enable external trackers after GraphQL migration
|
|
141
|
+
[], false, false, false);
|
|
164
142
|
}
|
|
165
143
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
166
|
-
}, [props.caseComments
|
|
167
|
-
const onAttachmentRemove = (uuid_removed) => {
|
|
168
|
-
updateAttacmentsAfterRemoval(dispatchDiscussion, uuid_removed, allDiscussions, discussionFiltersListState);
|
|
169
|
-
};
|
|
170
|
-
const onFeedbackUpdate = (comment_id, feedback) => {
|
|
171
|
-
updateCommentStateFeedback(dispatchDiscussion, comment_id, feedback, allDiscussions);
|
|
172
|
-
};
|
|
144
|
+
}, [props.caseComments]);
|
|
173
145
|
const onCommentAdded = () => __awaiter(this, void 0, void 0, function* () {
|
|
174
|
-
|
|
146
|
+
try {
|
|
147
|
+
yield props.refetchComments();
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
console.error('Failed to refetch comments:', e);
|
|
151
|
+
}
|
|
175
152
|
dtmTrackEventCaseStepEncountered('comment', caseNumber, product, version);
|
|
176
153
|
});
|
|
177
|
-
const onAttachmentAdded = () => __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
ToastNotification.addSuccessMessage(t('Attachment(s) uploaded successfully'));
|
|
179
|
-
yield updateDiscussionStateAttachments(dispatchDiscussion, caseNumber, allDiscussions, sort, loggedInUsersAccount.data.secureSupport, discussionFiltersListState, dispatchCaseDetailsHydraAttachments);
|
|
180
|
-
});
|
|
181
154
|
const onReply = (commentText, commentCreator, isPublic) => {
|
|
182
155
|
var _a;
|
|
183
156
|
setReplyingToPrivateComment(!isPublic);
|
|
@@ -191,11 +164,11 @@ export default function CaseDiscussion(props) {
|
|
|
191
164
|
clearReplyComment(dispatchDiscussion);
|
|
192
165
|
setReplyingToPrivateComment(null);
|
|
193
166
|
};
|
|
167
|
+
/** Strips special chars to prevent regex injection, then HTML-escapes via DOM round-trip to prevent XSS. */
|
|
194
168
|
const sanitizedSearchInput = (value) => {
|
|
195
169
|
if (!value)
|
|
196
170
|
return '';
|
|
197
171
|
const sanitizedValue = value.replace(/[^a-zA-Z0-9]/g, '');
|
|
198
|
-
// To escape HTML-like characters (e.g., <, >, &) in sanitizedValue
|
|
199
172
|
const div = document.createElement('div');
|
|
200
173
|
div.textContent = sanitizedValue;
|
|
201
174
|
return div.innerHTML;
|
|
@@ -209,10 +182,10 @@ export default function CaseDiscussion(props) {
|
|
|
209
182
|
isCommentSearchCleared && setIsCommentSearchCleared(false);
|
|
210
183
|
};
|
|
211
184
|
const highlightSearchResults = (searchTerm) => {
|
|
185
|
+
// Delay allows the DOM (especially virtualized rows) to finish rendering before mark.js can highlight matches.
|
|
212
186
|
setTimeout(() => {
|
|
213
|
-
// to mark attachment link button text
|
|
214
187
|
if (!isEmpty(sanitizedSearchInput(searchTerm))) {
|
|
215
|
-
const sanitizedSearchTerm = sanitizedSearchInput(searchTerm);
|
|
188
|
+
const sanitizedSearchTerm = sanitizedSearchInput(searchTerm);
|
|
216
189
|
document.querySelectorAll('button.attachment-download-btn').forEach((button) => {
|
|
217
190
|
var _a, _b;
|
|
218
191
|
if ((_a = button === null || button === void 0 ? void 0 : button.textContent) === null || _a === void 0 ? void 0 : _a.includes(sanitizedSearchTerm)) {
|
|
@@ -226,9 +199,6 @@ export default function CaseDiscussion(props) {
|
|
|
226
199
|
done: () => {
|
|
227
200
|
if (isEmpty(searchTerm))
|
|
228
201
|
return;
|
|
229
|
-
// removed { separateWordSearch: false }
|
|
230
|
-
// so the search term is split into individual words, and each word is matched separately.
|
|
231
|
-
// Search Term: "frontend developer" Matches: Text containing "frontend" or "developer".
|
|
232
202
|
markInstance.mark(searchTerm);
|
|
233
203
|
},
|
|
234
204
|
});
|
|
@@ -240,34 +210,52 @@ export default function CaseDiscussion(props) {
|
|
|
240
210
|
highlightSearchResults('');
|
|
241
211
|
setSearchResult([]);
|
|
242
212
|
if (cId === discussionIdFromUrl) {
|
|
243
|
-
// reason to reset activeElementId if comment id is same in the url on click jump to comment button
|
|
244
|
-
// we need to re compute filtered comments after clear search results.
|
|
245
|
-
// it will call useEffect and will set virtual comment Index(setVRCommentIndex())
|
|
246
213
|
activeElementId.current = '';
|
|
247
214
|
}
|
|
248
215
|
};
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
216
|
+
// TODO: Re-enable after GraphQL migration of attachments
|
|
217
|
+
// const onAttachmentRemove = (uuid_removed) => {
|
|
218
|
+
// updateAttacmentsAfterRemoval(dispatchDiscussion, uuid_removed, allDiscussions, discussionFiltersListState);
|
|
219
|
+
// };
|
|
220
|
+
// TODO: Re-enable after GraphQL migration of attachments
|
|
221
|
+
// const onAttachmentAdded = async () => {
|
|
222
|
+
// ToastNotification.addSuccessMessage(t('Attachment(s) uploaded successfully'));
|
|
223
|
+
// await updateDiscussionStateAttachments(
|
|
224
|
+
// dispatchDiscussion,
|
|
225
|
+
// caseNumber,
|
|
226
|
+
// allDiscussions,
|
|
227
|
+
// sort,
|
|
228
|
+
// loggedInUsersAccount.data.secureSupport,
|
|
229
|
+
// discussionFiltersListState,
|
|
230
|
+
// dispatchCaseDetailsHydraAttachments
|
|
231
|
+
// );
|
|
232
|
+
// };
|
|
233
|
+
// TODO: Re-enable after GraphQL migration of attachments
|
|
234
|
+
// const onMetadataUpdate = (attachmentId: string, updatedAttachment) => {
|
|
235
|
+
// updateAttachment(dispatchDiscussion, attachmentId, updatedAttachment, allDiscussions);
|
|
236
|
+
// };
|
|
237
|
+
// TODO: Re-enable after GraphQL migration of attachments
|
|
238
|
+
// const downloadAttachment = async ({ caseNumber, uuid, name }) => {
|
|
239
|
+
// const tempToastId = ToastNotification.addInfoMessage(t('Starting file download'));
|
|
240
|
+
// try {
|
|
241
|
+
// await caseAttachments.downloadAttachmentS3(
|
|
242
|
+
// caseNumber,
|
|
243
|
+
// uuid,
|
|
244
|
+
// name,
|
|
245
|
+
// false,
|
|
246
|
+
// loggedInUsersAccount.data.secureSupport
|
|
247
|
+
// );
|
|
248
|
+
// } catch (e) {
|
|
249
|
+
// ToastNotification.addDangerMessage(
|
|
250
|
+
// t(`Could not download {{filename}}: {{error}}`, {
|
|
251
|
+
// filename: name,
|
|
252
|
+
// error: e?.message,
|
|
253
|
+
// })
|
|
254
|
+
// );
|
|
255
|
+
// } finally {
|
|
256
|
+
// tempToastId && ToastNotification.clearToast(tempToastId);
|
|
257
|
+
// }
|
|
258
|
+
// };
|
|
271
259
|
useEffect(() => {
|
|
272
260
|
if (discussionSectionWidth && shouldRenderRVComponent) {
|
|
273
261
|
cellMeasureCache && cellMeasureCache.clearAll();
|
|
@@ -282,7 +270,6 @@ export default function CaseDiscussion(props) {
|
|
|
282
270
|
return (React.createElement(WindowScroller, { ref: windowScrollerRef, onScroll: handleScroll }, ({ height, registerChild, onChildScroll, isScrolling, scrollTop }) => {
|
|
283
271
|
return (React.createElement("div", { ref: commentRef, "data-tracking-id": "vr-case-comments" },
|
|
284
272
|
React.createElement(AutoSizer, { disableHeight: true }, ({ width }) => {
|
|
285
|
-
// setTimeout to update state in the next tick and avoid bad setState warnings
|
|
286
273
|
discussionSectionWidth !== width &&
|
|
287
274
|
setTimeout(() => setDiscussionSectionWidth(width), 0);
|
|
288
275
|
return (React.createElement("div", { ref: registerChild },
|
|
@@ -295,17 +282,18 @@ export default function CaseDiscussion(props) {
|
|
|
295
282
|
const renderCaseCommentElement = (discussion) => {
|
|
296
283
|
if (isEmpty(discussion) || isEmpty(discussion.item))
|
|
297
284
|
return null;
|
|
298
|
-
return (React.createElement("div", { "data-tracking-id": "discussion-elements", key: discussion.item.id },
|
|
299
|
-
discussion.discussionType === DiscussionType.COMMENT && (React.createElement(CaseComments, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, comment: discussion.item, onFeedBackUpdate: onFeedbackUpdate, feedback: discussion.feedback, accountNumber: props.accountNumber, onReply: onReply, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment, downloadAttachment: downloadAttachment })),
|
|
300
|
-
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 })),
|
|
301
|
-
discussion.discussionType === DiscussionType.CHAT && (React.createElement(CaseChat, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, chat: discussion.item, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment })),
|
|
302
|
-
discussion.discussionType === DiscussionType.EXTERNAL_TRACKER && (React.createElement(CaseExternalTrackerUpdate, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, trackerUpdate: discussion.item, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment }))));
|
|
285
|
+
return (React.createElement("div", { "data-tracking-id": "discussion-elements", key: discussion.item.id }, 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: () => { } }))));
|
|
303
286
|
};
|
|
304
|
-
const rowRenderer = ({ index, parent, key, style }) => {
|
|
287
|
+
const rowRenderer = ({ index, parent, key, style, }) => {
|
|
305
288
|
const discussion = comuteSearchedComments[index];
|
|
306
289
|
return (React.createElement(CellMeasurer, { key: key, cache: cellMeasureCache, parent: parent, columnIndex: 0, rowIndex: index },
|
|
307
290
|
React.createElement("div", { className: "comment-virtualized-row", key: key, style: style }, renderCaseCommentElement(discussion))));
|
|
308
291
|
};
|
|
292
|
+
/**
|
|
293
|
+
* One-shot scroll override used after search/filter changes.
|
|
294
|
+
* Resets the virtualized list to the top, then yields control back to
|
|
295
|
+
* WindowScroller's default onChildScroll for subsequent scroll events.
|
|
296
|
+
*/
|
|
309
297
|
const customChildScroll = ({ scrollTop }) => {
|
|
310
298
|
var _a;
|
|
311
299
|
if (!canUpdateScrollTop) {
|
|
@@ -318,23 +306,25 @@ export default function CaseDiscussion(props) {
|
|
|
318
306
|
};
|
|
319
307
|
const handleScroll = ({ scrollTop }) => {
|
|
320
308
|
var _a, _b, _c, _d, _e, _f;
|
|
321
|
-
// here we are doing couple of things
|
|
322
|
-
// 1. check scroll position on the first comment, 2. set scrollposition as par window top
|
|
323
|
-
// 3. if user click on jump to comment button then select row as per commentid and adding css class.
|
|
324
309
|
isCommentSearchCleared && setIsCommentSearchCleared(false);
|
|
325
310
|
if (listRef && commentRef) {
|
|
311
|
+
// Skip one scroll cycle after a search/filter reset to let customChildScroll re-sync
|
|
326
312
|
if (!canUpdateScrollTop) {
|
|
327
313
|
setCanUpdateScrollTop(true);
|
|
328
314
|
return;
|
|
329
315
|
}
|
|
330
316
|
const commentTop = (_b = (_a = commentRef === null || commentRef === void 0 ? void 0 : commentRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.top;
|
|
317
|
+
// Re-apply search highlights on scroll since virtualized rows re-mount
|
|
331
318
|
!isEmpty(searchCommentText) && highlightSearchResults(searchCommentText);
|
|
319
|
+
// Normal browsing or comment section visible above viewport — sync list position
|
|
332
320
|
if (isEmpty(discussionIdFromUrl) || commentTop > 0) {
|
|
333
321
|
(_c = listRef === null || listRef === void 0 ? void 0 : listRef.current) === null || _c === void 0 ? void 0 : _c.scrollToPosition(commentTop > 0 ? 0 : Math.abs(commentTop));
|
|
334
322
|
}
|
|
335
323
|
else if (commentTop < 0 && !isEmpty(discussionIdFromUrl) && !isJumpToCommentClicked) {
|
|
324
|
+
// Deep-link navigation: let WindowScroller drive the list scroll position
|
|
336
325
|
(_d = listRef === null || listRef === void 0 ? void 0 : listRef.current) === null || _d === void 0 ? void 0 : _d.scrollToPosition(scrollTop);
|
|
337
326
|
}
|
|
327
|
+
// After a "jump to comment" click, scroll the virtualized list to the target row
|
|
338
328
|
if (isJumpToCommentClicked) {
|
|
339
329
|
(_e = listRef === null || listRef === void 0 ? void 0 : listRef.current) === null || _e === void 0 ? void 0 : _e.scrollToRow(commentIndex);
|
|
340
330
|
(_f = windowScrollerRef === null || windowScrollerRef === void 0 ? void 0 : windowScrollerRef.current) === null || _f === void 0 ? void 0 : _f.updatePosition();
|
|
@@ -342,7 +332,6 @@ export default function CaseDiscussion(props) {
|
|
|
342
332
|
}
|
|
343
333
|
}
|
|
344
334
|
};
|
|
345
|
-
const list = discussionFiltersListState.filter((filter) => filter.canSee);
|
|
346
335
|
useEffect(() => {
|
|
347
336
|
if (isPostingRemoteRequestCommentCompleted) {
|
|
348
337
|
onCommentAdded();
|
|
@@ -350,59 +339,32 @@ export default function CaseDiscussion(props) {
|
|
|
350
339
|
}
|
|
351
340
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
352
341
|
}, [isPostingRemoteRequestCommentCompleted]);
|
|
353
|
-
const onToggleClick = (e) => {
|
|
354
|
-
e.stopPropagation();
|
|
355
|
-
setIsOpen(!isOpen);
|
|
356
|
-
};
|
|
357
342
|
const onSortToggleClick = (e) => {
|
|
358
343
|
e.stopPropagation();
|
|
359
344
|
setIsSortOpen(!isSortOpen);
|
|
360
345
|
};
|
|
361
|
-
const
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
: prevSelectedFiltersValue;
|
|
368
|
-
setFilter(dispatchDiscussion, newSelectedFilters, discussionFiltersListState);
|
|
369
|
-
shouldRenderRVComponent && setCanUpdateScrollTop(false);
|
|
370
|
-
setSelectedFilterItems(prevSelectedFiltersValue);
|
|
371
|
-
};
|
|
372
|
-
const toggle = (toggleRef) => (React.createElement(MenuToggle, { ref: toggleRef, onClick: onToggleClick, isExpanded: isOpen, isFullWidth: true }, getDropdownBtnPlaceholder(t('Select a filter'), list.filter((i) => i.isSelected).map((i) => i.filterLabel), ' ', list.length, t('All comments'))));
|
|
373
|
-
const onSortSelect = (_event, selectedSort) => {
|
|
374
|
-
setSort(dispatchDiscussion, selectedSort, allDiscussions);
|
|
375
|
-
setSortSelected(selectedSort.value);
|
|
346
|
+
const onSortSelect = (_event, value) => {
|
|
347
|
+
const selectedSort = discussionSortOrderConst.find((option) => option.name === value);
|
|
348
|
+
if (selectedSort) {
|
|
349
|
+
setSort(dispatchDiscussion, selectedSort, allDiscussions);
|
|
350
|
+
setSortSelected(selectedSort.name);
|
|
351
|
+
}
|
|
376
352
|
setIsSortOpen(false);
|
|
377
353
|
};
|
|
378
354
|
const onSortToggle = (toggleRef) => (React.createElement(MenuToggle, { ref: toggleRef, onClick: onSortToggleClick, isExpanded: isSortOpen, isFullWidth: true }, sort.name));
|
|
379
355
|
return (React.createElement(React.Fragment, null,
|
|
380
356
|
React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading post comment section') } },
|
|
381
|
-
React.createElement(
|
|
382
|
-
|
|
383
|
-
React.createElement(
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
(screenSessionRequested && allDiscussions.length === 0) }),
|
|
387
|
-
!caseAttachmentHydra.isFetching &&
|
|
388
|
-
!caseFeedbacksHydra.isFetching &&
|
|
389
|
-
!caseExternalTrackersUpdate.isFetching &&
|
|
390
|
-
!screenSessionRequested &&
|
|
391
|
-
allDiscussions.length === 0 && React.createElement(Trans, null, "No comments"),
|
|
392
|
-
!caseAttachmentHydra.isFetching &&
|
|
393
|
-
!caseFeedbacksHydra.isFetching &&
|
|
394
|
-
!caseExternalTrackersUpdate.isFetching &&
|
|
395
|
-
allDiscussions.length !== 0 && (React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading comments. Try refreshing.') } },
|
|
357
|
+
React.createElement(PostComment, { caseNumber: caseNumber, allDiscussions: allDiscussions, onCommentAdded: onCommentAdded, commentText: replyCommentText, onCommentClear: resetReplyComment, commentCreator: replyCommentCreator, defaultIsPublic: replyingToPrivateComment === null ? replyingToPrivateComment : !replyingToPrivateComment })),
|
|
358
|
+
props.commentsLoading && allDiscussions.length === 0 && React.createElement(LoadingIndicator, { size: "sm" }),
|
|
359
|
+
props.commentsError && allDiscussions.length === 0 && (React.createElement(AlertMessage, { variant: AlertType.DANGER, show: true, title: t('Failed to load comments. Try refreshing.') })),
|
|
360
|
+
!props.commentsLoading && !props.commentsError && allDiscussions.length === 0 && (React.createElement(Trans, null, "No comments")),
|
|
361
|
+
allDiscussions.length !== 0 && (React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading comments. Try refreshing.') } },
|
|
396
362
|
React.createElement("div", { className: `pfe-l-grid pfe-m-all-6-col pfe-m-gutters push-bottom ${isExportingPDF ? 'hide-in-pdf' : ''}` },
|
|
397
|
-
React.createElement("div", { className: "pfe-m-12-col" }, allDiscussions.length > 20 && (React.createElement(CommentSearch, { caseDiscussions:
|
|
398
|
-
React.createElement("span", { className: "push-top-narrow" },
|
|
399
|
-
React.createElement("label", { htmlFor: "case-list-comments-dropdown", className: "pf-v6-u-mb-sm" }, t('Filter by')),
|
|
400
|
-
React.createElement(Select, { "data-tracking-id": "discussions-filter-comments-dropdown", id: "case-list-comments-dropdown", role: "menu", isOpen: isOpen, selected: selectedFilterItems, onSelect: onFilterSelect, onOpenChange: (isOpen) => setIsOpen(isOpen), toggle: toggle, popperProps: { direction: 'down', enableFlip: false }, zIndex: 9 },
|
|
401
|
-
React.createElement(SelectList, null, list.map((option) => (React.createElement(SelectOption, { hasCheckbox: true, value: option, isSelected: option.isSelected, isDisabled: option.isDisabled }, option.filterLabel)))))),
|
|
363
|
+
React.createElement("div", { className: "pfe-m-12-col" }, allDiscussions.length > 20 && (React.createElement(CommentSearch, { caseDiscussions: allDiscussions || [], onCommentSearch: onCaseCommentSearch, isCommentSearchCleared: isCommentSearchCleared }))),
|
|
402
364
|
React.createElement("span", { className: "push-top-narrow" },
|
|
403
365
|
React.createElement("label", { htmlFor: "se-discussion-sort", className: "pf-v6-u-mb-sm" }, t('Sort by')),
|
|
404
366
|
React.createElement(Select, { id: "se-discussion-sort", "data-tracking-id": "discussions-sort-dropdown", isOpen: isSortOpen, selected: sortSelected, onSelect: onSortSelect, onOpenChange: (isSortOpen) => setIsSortOpen(isSortOpen), toggle: onSortToggle, shouldFocusToggleOnSelect: true, popperProps: { direction: 'down', enableFlip: false }, zIndex: 9 },
|
|
405
|
-
React.createElement(SelectList, null, discussionSortOrderConst.map((option) => (React.createElement(SelectOption, { value: option, isSelected: isEqual(sort.name, option.name) }, option.name))))))),
|
|
367
|
+
React.createElement(SelectList, null, discussionSortOrderConst.map((option) => (React.createElement(SelectOption, { value: option.name, isSelected: isEqual(sort.name, option.name) }, option.name))))))),
|
|
406
368
|
React.createElement("div", { className: "support-comment-section" }, !shouldRenderRVComponent &&
|
|
407
369
|
!isSearchResultEmpty &&
|
|
408
370
|
comuteSearchedComments.map((discussion, index) => {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Dispatch, MutableRefObject } from 'react';
|
|
2
|
+
interface UseAttachmentUploadCompletionParams {
|
|
3
|
+
isUploadingAttachments: boolean;
|
|
4
|
+
hasSomeUnUploadedFiles: boolean;
|
|
5
|
+
isUploadingAttachmentPrevious: MutableRefObject<boolean>;
|
|
6
|
+
caseDispatch: Dispatch<any>;
|
|
7
|
+
isInternal: boolean;
|
|
8
|
+
status: string | undefined;
|
|
9
|
+
resetAttachmentSection: () => void;
|
|
10
|
+
onAttachmentAdded: () => void;
|
|
11
|
+
setCssCommentAgreed: (v: boolean) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function useAttachmentUploadCompletion({ isUploadingAttachments, hasSomeUnUploadedFiles, isUploadingAttachmentPrevious, caseDispatch, isInternal, status, resetAttachmentSection, onAttachmentAdded, setCssCommentAgreed, }: UseAttachmentUploadCompletionParams): void;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=useAttachmentUploadCompletion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAttachmentUploadCompletion.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAa,MAAM,OAAO,CAAC;AAK9D,UAAU,mCAAmC;IACzC,sBAAsB,EAAE,OAAO,CAAC;IAChC,sBAAsB,EAAE,OAAO,CAAC;IAChC,6BAA6B,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACzD,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,sBAAsB,EAAE,MAAM,IAAI,CAAC;IACnC,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,mBAAmB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7C;AAED,wBAAgB,6BAA6B,CAAC,EAC1C,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,YAAY,EACZ,UAAU,EACV,MAAM,EACN,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,GACtB,EAAE,mCAAmC,QAiBrC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ToastNotification } from '@rh-support/components';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { checkForCaseStatusToggleOnAttachOrComment } from '../../../../../reducers/CaseReducer';
|
|
5
|
+
export function useAttachmentUploadCompletion({ isUploadingAttachments, hasSomeUnUploadedFiles, isUploadingAttachmentPrevious, caseDispatch, isInternal, status, resetAttachmentSection, onAttachmentAdded, setCssCommentAgreed, }) {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const justFinished = isUploadingAttachmentPrevious.current && !isUploadingAttachments && !hasSomeUnUploadedFiles;
|
|
9
|
+
if (justFinished) {
|
|
10
|
+
ToastNotification.addSuccessMessage(t('Attachment(s) uploaded successfully'));
|
|
11
|
+
checkForCaseStatusToggleOnAttachOrComment(caseDispatch, isInternal, status);
|
|
12
|
+
resetAttachmentSection();
|
|
13
|
+
onAttachmentAdded();
|
|
14
|
+
setCssCommentAgreed(false);
|
|
15
|
+
}
|
|
16
|
+
isUploadingAttachmentPrevious.current = isUploadingAttachments;
|
|
17
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18
|
+
}, [isUploadingAttachments]);
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EditorMode } from '@rh-support/components';
|
|
2
|
+
import { Dispatch, SetStateAction } from 'react';
|
|
3
|
+
interface UseCommentDraftsParams {
|
|
4
|
+
caseNumber: string;
|
|
5
|
+
loggedInUserSSO: string;
|
|
6
|
+
commentSignature: string;
|
|
7
|
+
setCommentText: Dispatch<SetStateAction<string>>;
|
|
8
|
+
setCommentType: Dispatch<SetStateAction<EditorMode>>;
|
|
9
|
+
setIsPublic: Dispatch<SetStateAction<boolean | undefined>>;
|
|
10
|
+
applySignature: (text: string) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function useCommentDrafts({ caseNumber, loggedInUserSSO, commentSignature, setCommentText, setCommentType, setIsPublic, applySignature, }: UseCommentDraftsParams): {
|
|
13
|
+
saveDraft: (...args: any[]) => void;
|
|
14
|
+
clearDraft: () => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=useCommentDrafts.d.ts.map
|
package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCommentDrafts.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useCommentDrafts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,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,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,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,cAAc,EACd,WAAW,EACX,cAAc,GACjB,EAAE,sBAAsB;;;EAgDxB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { debounce } from '@patternfly/react-core';
|
|
11
|
+
import { useEffect, useMemo } from 'react';
|
|
12
|
+
import { CaseDetailsCacheNamespaces } from '../../../../../enums/cache';
|
|
13
|
+
import { CaseDetailsCacheUtils } from '../../../../../utils/caseDetailsCacheUtils';
|
|
14
|
+
export function useCommentDrafts({ caseNumber, loggedInUserSSO, commentSignature, setCommentText, setCommentType, setIsPublic, applySignature, }) {
|
|
15
|
+
const saveDraft = useMemo(() => debounce(function (value, mode, publicFlag) {
|
|
16
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
const { value: prevDraftComments = {} } = (yield CaseDetailsCacheUtils.get(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO)) || {};
|
|
18
|
+
prevDraftComments[caseNumber] = { text: value, privateFlag: !publicFlag, type: mode };
|
|
19
|
+
CaseDetailsCacheUtils.set(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO, {
|
|
20
|
+
value: prevDraftComments,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}, 500), [caseNumber, loggedInUserSSO]);
|
|
24
|
+
const clearDraft = () => __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const { value: prevDraftComments = {} } = (yield CaseDetailsCacheUtils.get(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO)) || {};
|
|
26
|
+
delete prevDraftComments[caseNumber];
|
|
27
|
+
CaseDetailsCacheUtils.set(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO, {
|
|
28
|
+
value: prevDraftComments,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
function loadDraft() {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
var _a;
|
|
35
|
+
const { value: draftComments = {} } = (yield CaseDetailsCacheUtils.get(CaseDetailsCacheNamespaces.COMMENTS_DRAFT.name, loggedInUserSSO)) || {};
|
|
36
|
+
const draft = draftComments[caseNumber];
|
|
37
|
+
if (!((_a = draft === null || draft === void 0 ? void 0 : draft.text) === null || _a === void 0 ? void 0 : _a.trim()))
|
|
38
|
+
return;
|
|
39
|
+
applySignature(draft.text);
|
|
40
|
+
if (draft.privateFlag)
|
|
41
|
+
setIsPublic(false);
|
|
42
|
+
setCommentType(draft.type);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
loadDraft();
|
|
46
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
|
+
}, [commentSignature]);
|
|
48
|
+
return { saveDraft, clearDraft };
|
|
49
|
+
}
|
|
@@ -5,9 +5,13 @@ interface IProps {
|
|
|
5
5
|
commentText?: string;
|
|
6
6
|
commentCreator?: string;
|
|
7
7
|
onCommentAdded?: () => Promise<void>;
|
|
8
|
-
onAttachmentAdded?: () => void;
|
|
9
|
-
onAttachmentRemove?: (uuid: string) => void;
|
|
10
8
|
onCommentClear?: () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Controls the initial visibility toggle state.
|
|
11
|
+
* - `true` / `false` — sets comment visibility to public/private.
|
|
12
|
+
* - `null` — resets to the default (public).
|
|
13
|
+
* - `undefined` — same as omitting the prop.
|
|
14
|
+
*/
|
|
11
15
|
defaultIsPublic?: boolean;
|
|
12
16
|
allDiscussions: IDiscussion[];
|
|
13
17
|
}
|