@rh-support/troubleshoot 2.6.306 → 2.6.308
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/CaseDetailsTabs.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/CaseDetailsTabs.js +25 -21
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseAttachment.js +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.js +103 -82
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CommentSearch.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/CommentSearch.js +3 -2
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/DiscussionItemLink.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/DiscussionItemLink.js +7 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/JumpAndCopyLink.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/JumpAndCopyLink.js +8 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.d.ts +8 -3
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.js +11 -9
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.d.ts.map +1 -1
- package/lib/esm/components/CaseEditView/Tabs/CaseDiscussion/PostComment.js +33 -17
- package/lib/esm/components/shared/fileUpload/FileLister.js +1 -1
- package/lib/esm/components/shared/fileUpload/reducer/AttachmentHelper.d.ts +11 -2
- package/lib/esm/components/shared/fileUpload/reducer/AttachmentHelper.d.ts.map +1 -1
- package/lib/esm/components/shared/fileUpload/reducer/AttachmentHelper.js +65 -9
- package/lib/esm/components/shared/fileUpload/reducer/AttachmentReducer.d.ts +5 -1
- package/lib/esm/components/shared/fileUpload/reducer/AttachmentReducer.d.ts.map +1 -1
- package/lib/esm/components/shared/fileUpload/reducer/AttachmentReducer.js +23 -1
- package/lib/esm/components/shared/fileUpload/types/index.d.ts +2 -0
- package/lib/esm/components/shared/fileUpload/types/index.d.ts.map +1 -1
- package/lib/esm/components/shared/fileUpload/useFileUploader.d.ts.map +1 -1
- package/lib/esm/components/shared/fileUpload/useFileUploader.js +7 -1
- package/lib/esm/css/case.css +12 -7
- package/lib/esm/hooks/useCaseComments/mapCaseComment.d.ts +1 -1
- package/lib/esm/hooks/useCaseComments/mapCaseComment.d.ts.map +1 -1
- package/lib/esm/hooks/useCaseComments/mapCaseComment.js +13 -2
- package/lib/esm/reducers/CaseDiscussionTabReducer.d.ts.map +1 -1
- package/lib/esm/reducers/CaseDiscussionTabReducer.js +6 -2
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CaseDetailsTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/CaseDetailsTabs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CaseDetailsTabs.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/CaseDetailsTabs.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAa,MAAM,kBAAkB,CAAC;AA8BlE,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,mBAAmB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;CACnD;AACD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,qBAoT5C"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Content, ContentVariants,
|
|
1
|
+
import { Content, ContentVariants, Popover, Tab, TabContent, Tabs, TabsComponent, TabTitleText, } from '@patternfly/react-core';
|
|
2
2
|
import ExternalLinkAltIcon from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon';
|
|
3
3
|
import InfoCircleIcon from '@patternfly/react-icons/dist/js/icons/info-circle-icon';
|
|
4
4
|
import { ErrorBoundary, LoadingIndicator } from '@rh-support/components';
|
|
@@ -16,7 +16,8 @@ import { useCaseComments } from '../../hooks/useCaseComments';
|
|
|
16
16
|
import { PDFContext } from './PDFContainer';
|
|
17
17
|
import CaseDetailsManagement from './Tabs/CaseDetails/CaseDetailsManagement';
|
|
18
18
|
import CaseHistory from './Tabs/CaseHistory/CaseHistory';
|
|
19
|
-
|
|
19
|
+
// TODO: Re-enable AI Case Summary tab when ready
|
|
20
|
+
// import { CaseSummary } from './Tabs/CaseSummary/CaseSummary';
|
|
20
21
|
// TODO: Uncomment when External Trackers has a functioning GraphQL endpoint
|
|
21
22
|
// const RelatedTasks = React.lazy(
|
|
22
23
|
// () => import(/* webpackChunkName: 'CaseBugzilla' */ './Tabs/RelatedTasks/RelatedTasks')
|
|
@@ -56,8 +57,13 @@ export function CaseDetailsTabs(props) {
|
|
|
56
57
|
// resources.CASE_DETAILS,
|
|
57
58
|
// CaseDetailsFields.CASE_DETAILS_BUGZILLAS
|
|
58
59
|
// );
|
|
59
|
-
|
|
60
|
-
const
|
|
60
|
+
// TODO: Re-enable AI Case Summary tab when ready
|
|
61
|
+
// const caseSummaryViewConfig = getConfigField(
|
|
62
|
+
// pcmConfig.data,
|
|
63
|
+
// 'is_case_summary_view_active',
|
|
64
|
+
// PCM_CONFIG_FIELD_TYPE.STRING
|
|
65
|
+
// );
|
|
66
|
+
// const isCaseSummaryViewActive = caseSummaryViewConfig === '1';
|
|
61
67
|
const { isExportingPDF, pdfOption } = useContext(PDFContext);
|
|
62
68
|
const canSeeRMEs = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_RMES);
|
|
63
69
|
const [selectedTab, setSelectedTab] = useState(CaseDetailsTabsEnum.DISCUSSION);
|
|
@@ -70,7 +76,8 @@ export function CaseDetailsTabs(props) {
|
|
|
70
76
|
// TODO: Uncomment when External Trackers has a functioning GraphQL endpoint
|
|
71
77
|
// const relatedTasksRef: React.MutableRefObject<HTMLDivElement> = useRef(null);
|
|
72
78
|
const caseHistoryTabRef = useRef(null);
|
|
73
|
-
|
|
79
|
+
// TODO: Re-enable AI Case Summary tab when ready
|
|
80
|
+
// const generateAiCaseSummaryTabRef: React.MutableRefObject<HTMLDivElement> = useRef(null);
|
|
74
81
|
const tabsToRender = [];
|
|
75
82
|
const handleTabClick = (_event, tabIndex) => {
|
|
76
83
|
const index = Number(tabIndex);
|
|
@@ -146,17 +153,18 @@ export function CaseDetailsTabs(props) {
|
|
|
146
153
|
ref: caseHistoryTabRef,
|
|
147
154
|
component: React.createElement(CaseHistory, { caseNumber: caseNumber }),
|
|
148
155
|
});
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
// TODO: Re-enable AI Case Summary tab when ready
|
|
157
|
+
// !loggedInUsersAccount.data.secureSupport &&
|
|
158
|
+
// !loggedInUsersAccount.data.hasConfirmedStatesideSupport &&
|
|
159
|
+
// isCaseSummaryViewActive &&
|
|
160
|
+
// tabsToRender.push({
|
|
161
|
+
// 'data-tracking-id': 'generate-ai-case-summary-tab',
|
|
162
|
+
// title: CaseDetailsTabsEnum.GENERATE_AI_CASE_SUMMARY,
|
|
163
|
+
// key: 'generate ai case summary',
|
|
164
|
+
// routePath: 'generate-ai-case-summary',
|
|
165
|
+
// ref: generateAiCaseSummaryTabRef,
|
|
166
|
+
// component: <CaseSummary caseNumber={caseNumber} />,
|
|
167
|
+
// });
|
|
160
168
|
const getActiveTabKey = () => {
|
|
161
169
|
if (!activeTab)
|
|
162
170
|
return activeTabKey;
|
|
@@ -168,12 +176,8 @@ export function CaseDetailsTabs(props) {
|
|
|
168
176
|
? false
|
|
169
177
|
: true;
|
|
170
178
|
return (React.createElement("div", { className: "case-details-tabs", role: "region", ref: props.tabdRef },
|
|
171
|
-
React.createElement(Tabs, { className: isExportingPDF ? 'hide-in-pdf' : '', activeKey: getActiveTabKey(), component: TabsComponent.nav, onSelect: handleTabClick, "aria-label": t('Case details tabs') }, tabsToRender.map((tab, index) => (React.createElement(Tab, { eventKey: index, tabContentRef: tab.ref, tabContentId: `pf-tab-${index}-${tab.title.split(' ')[0]}-tabpanel`, key: tab.title, href: `#${props.basePath}/${tab.routePath}`, "data-tracking-id": tab['data-tracking-id'], title: React.createElement(TabTitleText, { className: tab.title === CaseDetailsTabsEnum.
|
|
172
|
-
tab.title === CaseDetailsTabsEnum.HISTORY
|
|
173
|
-
? 'tab-title-with-badge'
|
|
174
|
-
: undefined },
|
|
179
|
+
React.createElement(Tabs, { className: isExportingPDF ? 'hide-in-pdf' : '', activeKey: getActiveTabKey(), component: TabsComponent.nav, onSelect: handleTabClick, "aria-label": t('Case details tabs') }, tabsToRender.map((tab, index) => (React.createElement(Tab, { eventKey: index, tabContentRef: tab.ref, tabContentId: `pf-tab-${index}-${tab.title.split(' ')[0]}-tabpanel`, key: tab.title, href: `#${props.basePath}/${tab.routePath}`, "data-tracking-id": tab['data-tracking-id'], title: React.createElement(TabTitleText, { className: tab.title === CaseDetailsTabsEnum.HISTORY ? 'tab-title-with-badge' : undefined },
|
|
175
180
|
React.createElement(Trans, null, tab.title),
|
|
176
|
-
tab.title === CaseDetailsTabsEnum.GENERATE_AI_CASE_SUMMARY && (React.createElement(Label, { isCompact: true, variant: "outline", className: "preview-label" }, "Preview")),
|
|
177
181
|
tab.title === CaseDetailsTabsEnum.HISTORY && (React.createElement(Popover, { "aria-label": "Track support case evolution with case history", triggerAction: "hover", bodyContent: React.createElement(React.Fragment, null,
|
|
178
182
|
React.createElement("p", null, "Track support case evolution with case history"),
|
|
179
183
|
React.createElement("a", { href: "https://access.redhat.com/articles/7120652", target: "_blank", rel: "noreferrer" },
|
|
@@ -173,7 +173,7 @@ const CaseAttachment = React.forwardRef((props, ref) => {
|
|
|
173
173
|
React.createElement("h4", null,
|
|
174
174
|
React.createElement(Icon, { className: "pf-v6-u-mr-xs" },
|
|
175
175
|
React.createElement(PaperclipIcon, null)),
|
|
176
|
-
props.attachment.
|
|
176
|
+
props.attachment.createdBy),
|
|
177
177
|
React.createElement("time", { className: "text-right" }, formatDateTime(props.attachment.lastModifiedDate))),
|
|
178
178
|
React.createElement("div", { className: "comment-body" },
|
|
179
179
|
React.createElement(Trans, null, "Attached file"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CaseComments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CaseComments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AA4BvE,OAAO,KAAwC,MAAM,OAAO,CAAC;AAU7D,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAClF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChH;AAED,QAAA,MAAM,YAAY,4EA0VhB,CAAC;AAEH,eAAe,YAAY,CAAC"}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import FrownIcon from '@patternfly/react-icons/dist/js/icons/frown-icon';
|
|
14
|
-
import MehIcon from '@patternfly/react-icons/dist/js/icons/meh-icon';
|
|
15
|
-
import OutlinedFrownIcon from '@patternfly/react-icons/dist/js/icons/outlined-frown-icon';
|
|
16
|
-
import OutlinedMehIcon from '@patternfly/react-icons/dist/js/icons/outlined-meh-icon';
|
|
17
|
-
import OutlinedSmileIcon from '@patternfly/react-icons/dist/js/icons/outlined-smile-icon';
|
|
18
|
-
import SmileIcon from '@patternfly/react-icons/dist/js/icons/smile-icon';
|
|
1
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
2
|
+
// import { ICommentFeedback } from '@cee-eng/hydrajs/@types/api/public/commentFeedback';
|
|
3
|
+
import { EventTypes, linkifyBZIDs, linkifyWithCaseIDs, parseCommentMarkdown, processRME } from '@cee-eng/ui-toolkit';
|
|
4
|
+
import { Icon } from '@patternfly/react-core';
|
|
5
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
6
|
+
// import { Tooltip, TooltipPosition } from '@patternfly/react-core';
|
|
7
|
+
// import FrownIcon from '@patternfly/react-icons/dist/js/icons/frown-icon';
|
|
8
|
+
// import MehIcon from '@patternfly/react-icons/dist/js/icons/meh-icon';
|
|
9
|
+
// import OutlinedFrownIcon from '@patternfly/react-icons/dist/js/icons/outlined-frown-icon';
|
|
10
|
+
// import OutlinedMehIcon from '@patternfly/react-icons/dist/js/icons/outlined-meh-icon';
|
|
11
|
+
// import OutlinedSmileIcon from '@patternfly/react-icons/dist/js/icons/outlined-smile-icon';
|
|
12
|
+
// import SmileIcon from '@patternfly/react-icons/dist/js/icons/smile-icon';
|
|
19
13
|
import UserCircleIcon from '@patternfly/react-icons/dist/js/icons/user-circle-icon';
|
|
20
|
-
import { EditorMode
|
|
21
|
-
|
|
14
|
+
import { EditorMode } from '@rh-support/components';
|
|
15
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
16
|
+
// import { LoadingIndicator, ToastNotification } from '@rh-support/components';
|
|
17
|
+
import { AbilityContext,
|
|
18
|
+
// CaseDetailsFields, // TODO: Re-enable after GraphQL migration of feedback
|
|
19
|
+
CaseDiscussionFields, resourceActions, resources, } from '@rh-support/user-permissions';
|
|
22
20
|
import { formatDateTime, linkifyLinks } from '@rh-support/utils';
|
|
23
21
|
import DOMPurify from 'dompurify';
|
|
24
22
|
import isEmpty from 'lodash/isEmpty';
|
|
25
23
|
import isEqual from 'lodash/isEqual';
|
|
26
|
-
import React, { useContext, useEffect, useRef
|
|
27
|
-
import { Trans
|
|
24
|
+
import React, { useContext, useEffect, useRef } from 'react';
|
|
25
|
+
import { Trans } from 'react-i18next';
|
|
26
|
+
// TODO: Re-enable after GraphQL migration of feedback
|
|
27
|
+
// import { useTranslation } from 'react-i18next';
|
|
28
28
|
import { DiscussionType } from '../../../../reducers/CaseDiscussionTabReducer';
|
|
29
29
|
import { PDFContext } from '../../PDFContainer';
|
|
30
30
|
import { DiscussionItemLink } from './DiscussionItemLink';
|
|
@@ -33,55 +33,74 @@ const CaseComments = React.forwardRef((props, ref) => {
|
|
|
33
33
|
var _a;
|
|
34
34
|
const { caseNumber } = props;
|
|
35
35
|
const markdownRef = useRef(null);
|
|
36
|
-
|
|
36
|
+
// TODO: Re-enable `t` after GraphQL migration of feedback (Allowed Regression #5)
|
|
37
|
+
// const { t } = useTranslation();
|
|
37
38
|
const ability = useContext(AbilityContext);
|
|
38
39
|
const canSeePrivateComments = ability.can(resourceActions.PATCH, resources.CASE_COMMENTS, CaseDiscussionFields.VIEW_PRIVATE_COMMENT);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
41
|
+
// const canSeeFeedbackButtons =
|
|
42
|
+
// ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_FEEDBACK_BUTTONS) &&
|
|
43
|
+
// props.comment.isPublic &&
|
|
44
|
+
// props.comment.createdBy !== 'Automated Support Assistant';
|
|
45
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
46
|
+
// const [isFeedbackUpdating, setIsFeedbackUpdating] = useState(false);
|
|
43
47
|
const { isExportingPDF } = useContext(PDFContext);
|
|
44
48
|
const commentReply = (comment) => () => {
|
|
45
49
|
props.onReply(comment.commentBody, comment.createdBy, comment.isPublic);
|
|
46
50
|
};
|
|
47
51
|
const onJumpToComment = (commentId) => () => props.showJumpToComment && props.onJumpToComment && props.onJumpToComment(commentId);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
52
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
53
|
+
// const applyCommentFeedback = (comment: ICaseComment, feedback) => async (e) => {
|
|
54
|
+
// e.preventDefault();
|
|
55
|
+
// if (props.feedback === feedback) return;
|
|
56
|
+
// const commJson: ICommentFeedback = {
|
|
57
|
+
// feedback,
|
|
58
|
+
// accountNumber: props.accountNumber,
|
|
59
|
+
// commentId: comment.id,
|
|
60
|
+
// commentCreatedBy: comment.createdBy,
|
|
61
|
+
// };
|
|
62
|
+
// try {
|
|
63
|
+
// setIsFeedbackUpdating(true);
|
|
64
|
+
// if (props.feedback !== undefined) {
|
|
65
|
+
// await publicApi.commentFeedback.updateCommentFeedback(caseNumber, commJson);
|
|
66
|
+
// } else {
|
|
67
|
+
// await publicApi.commentFeedback.createCommentFeedback(caseNumber, commJson);
|
|
68
|
+
// }
|
|
69
|
+
// setIsFeedbackUpdating(false);
|
|
70
|
+
// props.onFeedBackUpdate(comment.id, feedback);
|
|
71
|
+
// ToastNotification.addSuccessMessage(t(`Comment feedback has been successfully updated`));
|
|
72
|
+
// } catch (e) {
|
|
73
|
+
// setIsFeedbackUpdating(false);
|
|
74
|
+
// ToastNotification.addDangerMessage(t(`Comment feedback failed to update`));
|
|
75
|
+
// }
|
|
76
|
+
// };
|
|
77
|
+
// TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
|
|
78
|
+
// const commentFeedbackButtons = (comment: ICaseComment, feedback: number) => (
|
|
79
|
+
// <span className="comment-feedback-buttons">
|
|
80
|
+
// <LoadingIndicator isInline={true} show={isFeedbackUpdating} />
|
|
81
|
+
// <Tooltip position={TooltipPosition.top} content={t('Positive feedback')}>
|
|
82
|
+
// <button className="btn btn-app btn-link" onClick={applyCommentFeedback(comment, 1)}
|
|
83
|
+
// data-tracking-id="case-comment-feedback-up" type="button">
|
|
84
|
+
// {feedback === 1 ? <SmileIcon title={t('Remove positive feedback')} />
|
|
85
|
+
// : <OutlinedSmileIcon title={t('Leave positive feedback')} />}
|
|
86
|
+
// </button>
|
|
87
|
+
// </Tooltip>
|
|
88
|
+
// <Tooltip position={TooltipPosition.top} content={t('Neutral feedback')}>
|
|
89
|
+
// <button className="btn btn-app btn-link" onClick={applyCommentFeedback(comment, 0)}
|
|
90
|
+
// data-tracking-id="case-comment-feedback-neutral" type="button">
|
|
91
|
+
// {feedback === 0 ? <MehIcon title={t('Remove neutral feedback')} />
|
|
92
|
+
// : <OutlinedMehIcon title={t('Leave neutral feedback')} />}
|
|
93
|
+
// </button>
|
|
94
|
+
// </Tooltip>
|
|
95
|
+
// <Tooltip position={TooltipPosition.top} content={t('Negative feedback')}>
|
|
96
|
+
// <button className="btn btn-app btn-link" onClick={applyCommentFeedback(comment, -1)}
|
|
97
|
+
// data-tracking-id="case-comment-feedback-down" type="button">
|
|
98
|
+
// {feedback === -1 ? <FrownIcon title={t('Remove negative feedback')} aria-label={t('Remove negative feedback')} />
|
|
99
|
+
// : <OutlinedFrownIcon title={t('Leave negative feedback')} aria-label={t('Leave negative feedback')} />}
|
|
100
|
+
// </button>
|
|
101
|
+
// </Tooltip>
|
|
102
|
+
// </span>
|
|
103
|
+
// );
|
|
85
104
|
const computeDiscussionCardCalss = (comment) => {
|
|
86
105
|
if (comment.createdByType === 'Associate' && comment.createdBy === 'Automated Support Assistant') {
|
|
87
106
|
return 'comment-automated';
|
|
@@ -134,8 +153,19 @@ const CaseComments = React.forwardRef((props, ref) => {
|
|
|
134
153
|
return React.createElement(Trans, null, "Automated comment");
|
|
135
154
|
}
|
|
136
155
|
};
|
|
156
|
+
const sanitizeHtml = (html) => {
|
|
157
|
+
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
|
|
158
|
+
if (node.tagName === 'A') {
|
|
159
|
+
node.setAttribute('target', '_blank');
|
|
160
|
+
node.setAttribute('rel', 'noopener noreferrer');
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
const clean = DOMPurify.sanitize(html, { ADD_ATTR: ['target', 'rel'] });
|
|
164
|
+
DOMPurify.removeHook('afterSanitizeAttributes');
|
|
165
|
+
return clean;
|
|
166
|
+
};
|
|
137
167
|
const commentText = (text) => {
|
|
138
|
-
return { __html:
|
|
168
|
+
return { __html: sanitizeHtml(text) };
|
|
139
169
|
};
|
|
140
170
|
// Transforms <strong> and <em> tags in HTML string to styled <span> tags to fix incorrect bold/italic rendering in exported PDF
|
|
141
171
|
function formatMarkdownHtmlForPDF(htmlString) {
|
|
@@ -158,7 +188,7 @@ const CaseComments = React.forwardRef((props, ref) => {
|
|
|
158
188
|
if (isExportingPDF) {
|
|
159
189
|
htmlString = formatMarkdownHtmlForPDF(htmlString);
|
|
160
190
|
}
|
|
161
|
-
return { __html:
|
|
191
|
+
return { __html: sanitizeHtml(htmlString) };
|
|
162
192
|
};
|
|
163
193
|
const onCommentAreaClick = (e) => {
|
|
164
194
|
let { event } = e.target['dataset'];
|
|
@@ -176,10 +206,13 @@ const CaseComments = React.forwardRef((props, ref) => {
|
|
|
176
206
|
const parseCommentHtml = (commentText, contentType) => {
|
|
177
207
|
let text = commentText;
|
|
178
208
|
if (contentType === EditorMode.PLAIN) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
209
|
+
// Normalize SFDC HTML line breaks to newlines before encoding
|
|
210
|
+
text = text
|
|
211
|
+
.replace(/<br\s*\/?>/gi, '\n')
|
|
212
|
+
.replace(/<\/p>/gi, '\n')
|
|
213
|
+
.replace(/<p>/gi, '');
|
|
214
|
+
// Escape all angle brackets so plaintext tags don't get swallowed by DOMPurify
|
|
215
|
+
text = text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
183
216
|
text = linkifyLinks(text);
|
|
184
217
|
text = linkifyWithCaseIDs(text);
|
|
185
218
|
text = linkifyBZIDs(text);
|
|
@@ -187,17 +220,6 @@ const CaseComments = React.forwardRef((props, ref) => {
|
|
|
187
220
|
}
|
|
188
221
|
return text;
|
|
189
222
|
};
|
|
190
|
-
/* Purpose of this method is to break the default HTML Entity rendering on the UI when in plaintext mode.
|
|
191
|
-
This is achieved by directly swapping the '&' in any html entity to `&` in e.g. &euro swaps to &euro
|
|
192
|
-
so it is rendered -> &euro on the UI instead of '€' */
|
|
193
|
-
//PCM-10968
|
|
194
|
-
const HTMLEntityChecker = (comment) => {
|
|
195
|
-
if (comment.includes('&')) {
|
|
196
|
-
return comment.replace(/&/g, '&');
|
|
197
|
-
}
|
|
198
|
-
else
|
|
199
|
-
return comment;
|
|
200
|
-
};
|
|
201
223
|
const computeCommentText = (comment) => {
|
|
202
224
|
const parseComment = parseCommentHtml(comment.commentBody, comment.contentType);
|
|
203
225
|
if (!isEmpty(comment.commentBody) && comment.contentType === EditorMode.MARKDOWN) {
|
|
@@ -237,7 +259,6 @@ const CaseComments = React.forwardRef((props, ref) => {
|
|
|
237
259
|
React.createElement("div", { className: "comment-body", onClick: onCommentAreaClick, ref: markdownRef }, computeCommentText(props.comment)),
|
|
238
260
|
React.createElement("footer", null,
|
|
239
261
|
React.createElement("span", { className: "comment-note" }, computeCommentFooter(props.comment)),
|
|
240
|
-
canSeeFeedbackButtons && commentFeedbackButtons(props.comment, props.feedback),
|
|
241
262
|
React.createElement("span", { className: "pull-right pf-v6-l-flex pf-m-align-items-center" },
|
|
242
263
|
props.showJumpToComment && (React.createElement(DiscussionItemLink, { onClick: onJumpToComment(props.comment.id), discussionType: DiscussionType.COMMENT, itemId: props.comment.id, caseNumber: caseNumber, isCopyLink: false },
|
|
243
264
|
React.createElement(Trans, null, "Jump to comment"))),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentSearch.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CommentSearch.tsx"],"names":[],"mappings":"AASA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,EAAkB,WAAW,EAAE,MAAM,+CAA+C,CAAC;AAE5F,UAAU,MAAM;IACZ,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,sBAAsB,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"CommentSearch.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CommentSearch.tsx"],"names":[],"mappings":"AASA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAGxC,OAAO,EAAkB,WAAW,EAAE,MAAM,+CAA+C,CAAC;AAE5F,UAAU,MAAM;IACZ,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,sBAAsB,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,qBAsG1C"}
|
|
@@ -82,8 +82,9 @@ export function CommentSearch(props) {
|
|
|
82
82
|
props.isCommentSearchCleared && !isEmpty(searchValue) && setSearchValue('');
|
|
83
83
|
return (React.createElement("form", { onSubmit: handleSubmit },
|
|
84
84
|
React.createElement("div", { className: "case-comment-input-container", "data-tracking-id": "case-comment-search" },
|
|
85
|
-
React.createElement(
|
|
86
|
-
|
|
85
|
+
React.createElement("div", { className: "case-comment-search-input-wrapper" },
|
|
86
|
+
React.createElement(TextInput, { type: "search", value: searchValue, placeholder: t('Search for a comment'), id: "case-comment-search", "aria-label": t('Search for a comment'), onChange: (_event, value) => onSearchValChange(value), "data-tracking-id": "case-comment-search-input" }),
|
|
87
|
+
searchValue && (React.createElement(Button, { icon: React.createElement(TimesIcon, null), onClick: clearSearchVal, className: "clear-btn", variant: "plain", "data-tracking-id": "case-comment-search-clear-button", "aria-label": t('Clear this search') }))),
|
|
87
88
|
React.createElement(Button, { variant: "secondary", type: "submit", "data-tracking-id": "case-comment-search-button" },
|
|
88
89
|
React.createElement(Trans, null, "Search")))));
|
|
89
90
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiscussionItemLink.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/DiscussionItemLink.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAE/E,UAAU,MAAM;IACZ,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAClB;AAUD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"DiscussionItemLink.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/DiscussionItemLink.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAE/E,UAAU,MAAM;IACZ,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;CAClB;AAUD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,qBAiC/C"}
|
|
@@ -19,8 +19,14 @@ export function DiscussionItemLink(props) {
|
|
|
19
19
|
};
|
|
20
20
|
return getStringifiedParams(Object.assign(Object.assign({}, requiredQueries), newQueryObj));
|
|
21
21
|
};
|
|
22
|
+
const handleClick = (e) => {
|
|
23
|
+
if (props.isCopyLink) {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
}
|
|
26
|
+
props.onClick();
|
|
27
|
+
};
|
|
22
28
|
return (React.createElement(Link, { replace: true, to: {
|
|
23
29
|
pathname: `/case/${props.caseNumber}/discussion`,
|
|
24
30
|
search: getQueryString(),
|
|
25
|
-
}, className: "case-public-private-link", onClick:
|
|
31
|
+
}, className: "case-public-private-link", onClick: handleClick, "data-tracking-id": `${!props.isCopyLink ? 'jumptocomment-' : 'case-'}${trackingIdMap[props.discussionType]}` }, props.children));
|
|
26
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JumpAndCopyLink.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/JumpAndCopyLink.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAG/E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,cAAc,CAAC;CAClC;
|
|
1
|
+
{"version":3,"file":"JumpAndCopyLink.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/JumpAndCopyLink.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAiB,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAG/E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,cAAc,CAAC;CAClC;AAQD,iBAAS,eAAe,CAAC,KAAK,EAAE,MAAM,qBA+BrC;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -4,13 +4,20 @@ import { useCopyToClipboard } from '@rh-support/components';
|
|
|
4
4
|
import React, { useRef } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { DiscussionItemLink } from './DiscussionItemLink';
|
|
7
|
+
function getAppBasePath() {
|
|
8
|
+
const path = window.location.pathname;
|
|
9
|
+
if (path.startsWith('/support-beta'))
|
|
10
|
+
return '/support-beta';
|
|
11
|
+
return '/support/cases';
|
|
12
|
+
}
|
|
7
13
|
function JumpAndCopyLink(props) {
|
|
8
14
|
const { t } = useTranslation();
|
|
9
15
|
const clipboardRefLink = useRef(null);
|
|
10
16
|
const queryString = `${props.discussionType}Id=${props.cardId}`;
|
|
17
|
+
const basePath = getAppBasePath();
|
|
11
18
|
const { clipboardText, copyToClipboard } = useCopyToClipboard(clipboardRefLink);
|
|
12
19
|
return (React.createElement(React.Fragment, null,
|
|
13
|
-
React.createElement("div", { ref: clipboardRefLink, style: { position: 'absolute', left: '-9999px' } }, `https://${window.location.host}
|
|
20
|
+
React.createElement("div", { ref: clipboardRefLink, style: { position: 'absolute', left: '-9999px' } }, `https://${window.location.host}${basePath}/#/case/${props.caseNumber}/discussion?${queryString}`),
|
|
14
21
|
React.createElement(DiscussionItemLink, { onClick: copyToClipboard, caseNumber: props.caseNumber, discussionType: props.discussionType, itemId: props.cardId, isCopyLink: true },
|
|
15
22
|
React.createElement(Popover, { position: PopoverPosition.top, bodyContent: (hide) => React.createElement("div", null, clipboardText), hasAutoWidth: true, showClose: false },
|
|
16
23
|
React.createElement(LinkIcon, { title: t('Copy link') })))));
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { Dispatch, MutableRefObject } from 'react';
|
|
2
2
|
interface UseAttachmentUploadCompletionParams {
|
|
3
3
|
isUploadingAttachments: boolean;
|
|
4
|
-
|
|
4
|
+
hasQueuedUploads: boolean;
|
|
5
|
+
hasAbortedOrFailed: boolean;
|
|
5
6
|
isUploadingAttachmentPrevious: MutableRefObject<boolean>;
|
|
6
7
|
caseDispatch: Dispatch<any>;
|
|
7
8
|
isInternal: boolean;
|
|
8
9
|
status: string | undefined;
|
|
9
10
|
resetAttachmentSection: () => void;
|
|
10
|
-
onAttachmentAdded: () => void;
|
|
11
11
|
setCssCommentAgreed: (v: boolean) => void;
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Batch cleanup after uploads settle.
|
|
15
|
+
* Per-file success already refreshes discussion and dismisses completed rows;
|
|
16
|
+
* this resets the panel when nothing aborted/failed remains.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useAttachmentUploadCompletion({ isUploadingAttachments, hasQueuedUploads, hasAbortedOrFailed, isUploadingAttachmentPrevious, caseDispatch, isInternal, status, resetAttachmentSection, setCssCommentAgreed, }: UseAttachmentUploadCompletionParams): void;
|
|
14
19
|
export {};
|
|
15
20
|
//# sourceMappingURL=useAttachmentUploadCompletion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAttachmentUploadCompletion.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAttachmentUploadCompletion.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment/useAttachmentUploadCompletion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAa,MAAM,OAAO,CAAC;AAI9D,UAAU,mCAAmC;IACzC,sBAAsB,EAAE,OAAO,CAAC;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,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,mBAAmB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,EAC1C,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,6BAA6B,EAC7B,YAAY,EACZ,UAAU,EACV,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACtB,EAAE,mCAAmC,QAerC"}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import { ToastNotification } from '@rh-support/components';
|
|
2
1
|
import { useEffect } from 'react';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
4
2
|
import { checkForCaseStatusToggleOnAttachOrComment } from '../../../../../reducers/CaseReducer';
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Batch cleanup after uploads settle.
|
|
5
|
+
* Per-file success already refreshes discussion and dismisses completed rows;
|
|
6
|
+
* this resets the panel when nothing aborted/failed remains.
|
|
7
|
+
*/
|
|
8
|
+
export function useAttachmentUploadCompletion({ isUploadingAttachments, hasQueuedUploads, hasAbortedOrFailed, isUploadingAttachmentPrevious, caseDispatch, isInternal, status, resetAttachmentSection, setCssCommentAgreed, }) {
|
|
7
9
|
useEffect(() => {
|
|
8
|
-
const justFinished = isUploadingAttachmentPrevious.current && !isUploadingAttachments && !
|
|
10
|
+
const justFinished = isUploadingAttachmentPrevious.current && !isUploadingAttachments && !hasQueuedUploads;
|
|
9
11
|
if (justFinished) {
|
|
10
|
-
|
|
12
|
+
if (!hasAbortedOrFailed) {
|
|
13
|
+
resetAttachmentSection();
|
|
14
|
+
}
|
|
11
15
|
checkForCaseStatusToggleOnAttachOrComment(caseDispatch, isInternal, status);
|
|
12
|
-
resetAttachmentSection();
|
|
13
|
-
onAttachmentAdded();
|
|
14
16
|
setCssCommentAgreed(false);
|
|
15
17
|
}
|
|
16
18
|
isUploadingAttachmentPrevious.current = isUploadingAttachments;
|
|
17
19
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18
|
-
}, [isUploadingAttachments]);
|
|
20
|
+
}, [isUploadingAttachments, hasQueuedUploads, hasAbortedOrFailed]);
|
|
19
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostComment.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA+D,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"PostComment.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/PostComment.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA+D,MAAM,OAAO,CAAC;AAMpF,OAAO,EAAE,WAAW,EAAE,MAAM,+CAA+C,CAAC;AAmB5E,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,WAAW,EAAE,CAAC;CACjC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,qBAucxC"}
|