@rh-support/troubleshoot 2.7.10 → 2.7.12

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Case.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/Case.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAS,mBAAmB,EAAiD,MAAM,kBAAkB,CAAC;AAoB7G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC;CACnC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,KAAK,EAAE,MAAM,qBAgRzC"}
1
+ {"version":3,"file":"Case.d.ts","sourceRoot":"","sources":["../../../../src/components/CaseEditView/Case.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAS,mBAAmB,EAAiD,MAAM,kBAAkB,CAAC;AAoB7G,UAAU,MAAM;IACZ,UAAU,EAAE,mBAAmB,CAAC;CACnC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,KAAK,EAAE,MAAM,qBA+QzC"}
@@ -20,10 +20,9 @@ import { Route, Switch, useLocation, useParams, useRouteMatch } from 'react-rout
20
20
  import { useCaseDispatch, useCaseSelector } from '../../context/CaseContext';
21
21
  import { useCaseDetailsPageDispatchContext } from '../../context/CaseDetailsPageContext';
22
22
  import { CaseReducerConstants } from '../../reducers/CaseConstNTypes';
23
- import { fetchAttachments, fetchCaseEscalations,
23
+ import { fetchAttachments, fetchCaseEscalations,
24
24
  // fetchExternalTrackers,
25
- // fetchFeedbacks,
26
- } from '../../reducers/CaseDetailsPageReducer';
25
+ fetchFeedbacks, } from '../../reducers/CaseDetailsPageReducer';
27
26
  import { setCaseAccountNumber } from '../../reducers/CaseReducer';
28
27
  import { ArchivedCaseBanner } from './ArchivedCaseBanner';
29
28
  import { CaseDetailsAside } from './CaseDetailsAside';
@@ -140,13 +139,9 @@ export default function Case(props) {
140
139
  // targetCaseNumber
141
140
  // );
142
141
  // }
143
- // TODO: Re-enable after GraphQL migration of feedback
144
- // if (canSeeFeedbackButtons) {
145
- // fetchFeedbacks(
146
- // (action) => currentCaseRef.current === targetCaseNumber && caseDetailsPageDispatch(action),
147
- // targetCaseNumber
148
- // );
149
- // }
142
+ if (canSeeFeedbackButtons) {
143
+ fetchFeedbacks((action) => currentCaseRef.current === targetCaseNumber && caseDetailsPageDispatch(action), targetCaseNumber);
144
+ }
150
145
  if (currentCaseRef.current === targetCaseNumber) {
151
146
  checkRemoteSessionFlag();
152
147
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AsaCommentFeedbackModal.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/AsaCommentFeedbackModal.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAIvB,CAAC;AAEX,UAAU,MAAM;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;CACpG;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,qBAiLpD"}
1
+ {"version":3,"file":"AsaCommentFeedbackModal.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/AsaCommentFeedbackModal.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAIvB,CAAC;AAEX,UAAU,MAAM;IACZ,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;CACpG;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,qBA+JpD"}
@@ -7,7 +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 { Button, Form, FormGroup, FormHelperText, HelperText, HelperTextItem, Icon, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, TextArea, ValidatedOptions, } from '@patternfly/react-core';
10
+ import { Button, Form, FormGroup, Icon, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, TextArea, } from '@patternfly/react-core';
11
11
  import OutlinedFrownIcon from '@patternfly/react-icons/dist/js/icons/outlined-frown-icon';
12
12
  import OutlinedMehIcon from '@patternfly/react-icons/dist/js/icons/outlined-meh-icon';
13
13
  import OutlinedSmileIcon from '@patternfly/react-icons/dist/js/icons/outlined-smile-icon';
@@ -25,12 +25,10 @@ export function AsaCommentFeedbackModal(props) {
25
25
  const [selectedFeedback, setSelectedFeedback] = useState(props.initialFeedback);
26
26
  const [feedbackReason, setFeedbackReason] = useState((_a = props.initialFeedbackReason) !== null && _a !== void 0 ? _a : '');
27
27
  const [showRatingError, setShowRatingError] = useState(false);
28
- const [showFeedbackTextError, setShowFeedbackTextError] = useState(false);
29
28
  const trimmedFeedbackReason = feedbackReason.trim();
30
29
  const savedFeedbackReason = (_b = props.initialFeedbackReason) !== null && _b !== void 0 ? _b : '';
31
30
  const hasChanges = selectedFeedback !== props.initialFeedback || feedbackReason !== savedFeedbackReason;
32
- const hasValidationError = showRatingError || showFeedbackTextError;
33
- const isSubmitDisabled = props.isSubmitting || hasValidationError;
31
+ const isSubmitDisabled = props.isSubmitting || showRatingError;
34
32
  useEffect(() => {
35
33
  var _a;
36
34
  if (props.isOpen) {
@@ -38,7 +36,6 @@ export function AsaCommentFeedbackModal(props) {
38
36
  setFeedbackReason((_a = props.initialFeedbackReason) !== null && _a !== void 0 ? _a : '');
39
37
  }
40
38
  setShowRatingError(false);
41
- setShowFeedbackTextError(false);
42
39
  }, [props.isOpen, props.initialFeedback, props.initialFeedbackReason]);
43
40
  const handleClose = () => {
44
41
  if (props.isSubmitting) {
@@ -52,10 +49,6 @@ export function AsaCommentFeedbackModal(props) {
52
49
  setShowRatingError(true);
53
50
  return;
54
51
  }
55
- if (trimmedFeedbackReason.length === 0) {
56
- setShowFeedbackTextError(true);
57
- return;
58
- }
59
52
  if (!hasChanges) {
60
53
  return;
61
54
  }
@@ -84,12 +77,8 @@ export function AsaCommentFeedbackModal(props) {
84
77
  })),
85
78
  showRatingError && selectedFeedback === undefined && (React.createElement("p", { className: "form-instructions form-invalid pf-v6-u-mt-sm" },
86
79
  React.createElement(Trans, null, "Please select a value")))),
87
- React.createElement(FormGroup, { label: t('How can we improve?'), isRequired: true, fieldId: "asa-comment-feedback-reason" },
88
- showFeedbackTextError && (React.createElement(FormHelperText, null,
89
- React.createElement(HelperText, null,
90
- React.createElement(HelperTextItem, { variant: ValidatedOptions.error }, t('Please enter your feedback'))))),
91
- React.createElement(TextArea, { id: "asa-comment-feedback-reason", name: "feedbackReason", value: feedbackReason, validated: showFeedbackTextError ? ValidatedOptions.error : ValidatedOptions.default, onChange: (_event, value) => {
92
- setShowFeedbackTextError(false);
80
+ React.createElement(FormGroup, { label: t('How can we improve?'), fieldId: "asa-comment-feedback-reason" },
81
+ React.createElement(TextArea, { id: "asa-comment-feedback-reason", name: "feedbackReason", value: feedbackReason, onChange: (_event, value) => {
93
82
  setFeedbackReason(value);
94
83
  }, placeholder: t('Describe your suggestion in details'), "aria-label": t('How can we improve?'), isDisabled: props.isSubmitting, resizeOrientation: "vertical" })),
95
84
  React.createElement("p", { className: "asa-feedback-privacy" },
@@ -1,10 +1,12 @@
1
1
  import { ICaseComment } from '@cee-eng/hydrajs/@types/api/public/case';
2
2
  import React from 'react';
3
+ export declare const AUTOMATED_SUPPORT_ASSISTANT = "Support AI Assistant Service Account";
3
4
  interface IProps {
4
5
  caseNumber: string;
5
6
  comment: ICaseComment;
6
7
  feedback: number;
7
- onFeedBackUpdate: (id: string, feedback: number) => void;
8
+ feedbackReason?: string;
9
+ onFeedBackUpdate: (id: string, feedback: number, feedbackReason?: string) => void;
8
10
  accountNumber: string;
9
11
  onReply: (author: string, commentId: string, timestamp: string) => void;
10
12
  showJumpToComment?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"CaseComments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AA2BvE,OAAO,KAAwC,MAAM,OAAO,CAAC;AAW7D,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChH;AAED,QAAA,MAAM,YAAY,4EAgXhB,CAAC;AAEH,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"CaseComments.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseComments.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAuBvE,OAAO,KAAkD,MAAM,OAAO,CAAC;AAUvE,eAAO,MAAM,2BAA2B,yCAAyC,CAAC;AAElF,UAAU,MAAM;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAClF,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAChH;AAED,QAAA,MAAM,YAAY,4EAkdhB,CAAC;AAEH,eAAe,YAAY,CAAC"}
@@ -1,105 +1,120 @@
1
- // TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
2
- // import { ICommentFeedback } from '@cee-eng/hydrajs/@types/api/public/commentFeedback';
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 { publicApi } from '@cee-eng/hydrajs';
3
11
  import { EventTypes, linkifyBZIDs, linkifyWithCaseIDs, 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';
12
+ import { Alert, Button, ButtonVariant, Icon, Tooltip, TooltipPosition } from '@patternfly/react-core';
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';
13
19
  import UserCircleIcon from '@patternfly/react-icons/dist/js/icons/user-circle-icon';
14
- // TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
15
- // import { LoadingIndicator, ToastNotification } from '@rh-support/components';
16
- import { AbilityContext,
17
- // CaseDetailsFields, // TODO: Re-enable after GraphQL migration of feedback
18
- CaseDiscussionFields, resourceActions, resources, } from '@rh-support/user-permissions';
20
+ import { LoadingIndicator, ToastNotification } from '@rh-support/components';
21
+ import { AbilityContext, CaseDetailsFields, CaseDiscussionFields, resourceActions, resources, } from '@rh-support/user-permissions';
19
22
  import { formatDateTime, linkifyLinks } from '@rh-support/utils';
20
23
  import DOMPurify from 'dompurify';
21
24
  import isEmpty from 'lodash/isEmpty';
22
25
  import isEqual from 'lodash/isEqual';
23
- import React, { useContext, useEffect, useRef } from 'react';
24
- import { Trans } from 'react-i18next';
25
- // TODO: Re-enable after GraphQL migration of feedback
26
- // import { useTranslation } from 'react-i18next';
26
+ import React, { useContext, useEffect, useRef, useState } from 'react';
27
+ import { Trans, useTranslation } from 'react-i18next';
27
28
  import { DiscussionType } from '../../../../reducers/CaseDiscussionTabReducer';
28
29
  import { linkifyHtmlTextNodes } from '../../../../utils/linkifyHtmlTextNodes';
29
30
  import { PDFContext } from '../../PDFContainer';
31
+ import { AsaCommentFeedbackModal } from './AsaCommentFeedbackModal';
30
32
  import { DiscussionItemLink } from './DiscussionItemLink';
31
33
  import { JumpAndCopyLink } from './JumpAndCopyLink';
34
+ export const AUTOMATED_SUPPORT_ASSISTANT = 'Support AI Assistant Service Account';
32
35
  const CaseComments = React.forwardRef((props, ref) => {
33
- var _a;
36
+ var _a, _b;
34
37
  const { caseNumber } = props;
35
38
  const markdownRef = useRef(null);
36
- // TODO: Re-enable `t` after GraphQL migration of feedback (Allowed Regression #5)
37
- // const { t } = useTranslation();
39
+ const { t } = useTranslation();
38
40
  const ability = useContext(AbilityContext);
39
41
  const canSeePrivateComments = ability.can(resourceActions.PATCH, resources.CASE_COMMENTS, CaseDiscussionFields.VIEW_PRIVATE_COMMENT);
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);
42
+ const isAsaComment = props.comment.createdBy === AUTOMATED_SUPPORT_ASSISTANT;
43
+ const canGiveCommentFeedback = ability.can(resourceActions.PATCH, resources.CASE_DETAILS, CaseDetailsFields.CASE_DETAILS_FEEDBACK_BUTTONS);
44
+ const canSeeFeedbackButtons = canGiveCommentFeedback && props.comment.isPublic && !isAsaComment;
45
+ const [isFeedbackUpdating, setIsFeedbackUpdating] = useState(false);
46
+ const [isAsaFeedbackModalOpen, setIsAsaFeedbackModalOpen] = useState(false);
47
+ const [savedFeedbackValue, setSavedFeedbackValue] = useState(props.feedback);
48
+ const [savedFeedbackReason, setSavedFeedbackReason] = useState((_a = props.feedbackReason) !== null && _a !== void 0 ? _a : '');
47
49
  const { isExportingPDF } = useContext(PDFContext);
50
+ useEffect(() => {
51
+ setSavedFeedbackValue(props.feedback);
52
+ }, [props.feedback]);
53
+ useEffect(() => {
54
+ var _a;
55
+ setSavedFeedbackReason((_a = props.feedbackReason) !== null && _a !== void 0 ? _a : '');
56
+ }, [props.feedbackReason]);
48
57
  const onJumpToComment = (commentId) => () => props.showJumpToComment && props.onJumpToComment && props.onJumpToComment(commentId);
49
- // TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
50
- // const applyCommentFeedback = (comment: ICaseComment, feedback) => async (e) => {
51
- // e.preventDefault();
52
- // if (props.feedback === feedback) return;
53
- // const commJson: ICommentFeedback = {
54
- // feedback,
55
- // accountNumber: props.accountNumber,
56
- // commentId: comment.id,
57
- // commentCreatedBy: comment.createdBy,
58
- // };
59
- // try {
60
- // setIsFeedbackUpdating(true);
61
- // if (props.feedback !== undefined) {
62
- // await publicApi.commentFeedback.updateCommentFeedback(caseNumber, commJson);
63
- // } else {
64
- // await publicApi.commentFeedback.createCommentFeedback(caseNumber, commJson);
65
- // }
66
- // setIsFeedbackUpdating(false);
67
- // props.onFeedBackUpdate(comment.id, feedback);
68
- // ToastNotification.addSuccessMessage(t(`Comment feedback has been successfully updated`));
69
- // } catch (e) {
70
- // setIsFeedbackUpdating(false);
71
- // ToastNotification.addDangerMessage(t(`Comment feedback failed to update`));
72
- // }
73
- // };
74
- // TODO: Re-enable after GraphQL migration of feedback (Allowed Regression #5)
75
- // const commentFeedbackButtons = (comment: ICaseComment, feedback: number) => (
76
- // <span className="comment-feedback-buttons">
77
- // <LoadingIndicator isInline={true} show={isFeedbackUpdating} />
78
- // <Tooltip position={TooltipPosition.top} content={t('Positive feedback')}>
79
- // <button className="btn btn-app btn-link" onClick={applyCommentFeedback(comment, 1)}
80
- // data-tracking-id="case-comment-feedback-up" type="button">
81
- // {feedback === 1 ? <SmileIcon title={t('Remove positive feedback')} />
82
- // : <OutlinedSmileIcon title={t('Leave positive feedback')} />}
83
- // </button>
84
- // </Tooltip>
85
- // <Tooltip position={TooltipPosition.top} content={t('Neutral feedback')}>
86
- // <button className="btn btn-app btn-link" onClick={applyCommentFeedback(comment, 0)}
87
- // data-tracking-id="case-comment-feedback-neutral" type="button">
88
- // {feedback === 0 ? <MehIcon title={t('Remove neutral feedback')} />
89
- // : <OutlinedMehIcon title={t('Leave neutral feedback')} />}
90
- // </button>
91
- // </Tooltip>
92
- // <Tooltip position={TooltipPosition.top} content={t('Negative feedback')}>
93
- // <button className="btn btn-app btn-link" onClick={applyCommentFeedback(comment, -1)}
94
- // data-tracking-id="case-comment-feedback-down" type="button">
95
- // {feedback === -1 ? <FrownIcon title={t('Remove negative feedback')} aria-label={t('Remove negative feedback')} />
96
- // : <OutlinedFrownIcon title={t('Leave negative feedback')} aria-label={t('Leave negative feedback')} />}
97
- // </button>
98
- // </Tooltip>
99
- // </span>
100
- // );
58
+ const applyCommentFeedback = (comment, feedback) => (e) => __awaiter(void 0, void 0, void 0, function* () {
59
+ e.preventDefault();
60
+ if (props.feedback === feedback) {
61
+ return;
62
+ }
63
+ yield submitCommentFeedback(comment, feedback);
64
+ });
65
+ const submitCommentFeedback = (comment, feedback, feedbackReason) => __awaiter(void 0, void 0, void 0, function* () {
66
+ var _a;
67
+ const commJson = Object.assign({ feedback, accountNumber: props.accountNumber, commentId: comment.id, commentCreatedBy: comment.createdBy }, (feedbackReason !== undefined ? { feedbackReason } : {}));
68
+ try {
69
+ setIsFeedbackUpdating(true);
70
+ const hasExistingFeedback = savedFeedbackValue !== undefined;
71
+ const response = hasExistingFeedback
72
+ ? yield publicApi.commentFeedback.updateCommentFeedback(caseNumber, commJson)
73
+ : yield publicApi.commentFeedback.createCommentFeedback(caseNumber, commJson);
74
+ setIsFeedbackUpdating(false);
75
+ const responseFeedback = (response === null || response === void 0 ? void 0 : response.feedback) !== undefined && (response === null || response === void 0 ? void 0 : response.feedback) !== null && `${response.feedback}` !== ''
76
+ ? parseInt(String(response.feedback), 10)
77
+ : feedback;
78
+ const savedFeedback = Number.isNaN(responseFeedback) ? feedback : responseFeedback;
79
+ const savedReason = (_a = response === null || response === void 0 ? void 0 : response.feedbackReason) !== null && _a !== void 0 ? _a : feedbackReason;
80
+ setSavedFeedbackValue(savedFeedback);
81
+ if (feedbackReason !== undefined) {
82
+ setSavedFeedbackReason(savedReason !== null && savedReason !== void 0 ? savedReason : '');
83
+ props.onFeedBackUpdate(comment.id, savedFeedback, savedReason !== null && savedReason !== void 0 ? savedReason : '');
84
+ }
85
+ else {
86
+ props.onFeedBackUpdate(comment.id, savedFeedback);
87
+ }
88
+ ToastNotification.addSuccessMessage(t(`Comment feedback has been successfully updated`));
89
+ return true;
90
+ }
91
+ catch (e) {
92
+ setIsFeedbackUpdating(false);
93
+ ToastNotification.addDangerMessage(t(`Comment feedback failed to update`));
94
+ return false;
95
+ }
96
+ });
97
+ const openAsaFeedbackModal = (e) => {
98
+ e === null || e === void 0 ? void 0 : e.preventDefault();
99
+ setIsAsaFeedbackModalOpen(true);
100
+ };
101
+ const onSubmitAsaFeedback = (feedback, feedbackReason) => __awaiter(void 0, void 0, void 0, function* () {
102
+ const didSubmit = yield submitCommentFeedback(props.comment, feedback, feedbackReason);
103
+ if (didSubmit) {
104
+ setIsAsaFeedbackModalOpen(false);
105
+ }
106
+ return didSubmit;
107
+ });
108
+ const commentFeedbackButtons = (comment, feedback) => (React.createElement("span", { className: "comment-feedback-buttons" },
109
+ React.createElement(LoadingIndicator, { isInline: true, show: isFeedbackUpdating }),
110
+ React.createElement(Tooltip, { position: TooltipPosition.top, content: t('Positive feedback') },
111
+ React.createElement("button", { className: "btn btn-app btn-link", onClick: applyCommentFeedback(comment, 1), "data-tracking-id": "case-comment-feedback-up", type: "button" }, feedback === 1 ? (React.createElement(SmileIcon, { title: t('Remove positive feedback') })) : (React.createElement(OutlinedSmileIcon, { title: t('Leave positive feedback') })))),
112
+ React.createElement(Tooltip, { position: TooltipPosition.top, content: t('Neutral feedback') },
113
+ React.createElement("button", { className: "btn btn-app btn-link", onClick: applyCommentFeedback(comment, 0), "data-tracking-id": "case-comment-feedback-neutral", type: "button" }, feedback === 0 ? (React.createElement(MehIcon, { title: t('Remove neutral feedback') })) : (React.createElement(OutlinedMehIcon, { title: t('Leave neutral feedback') })))),
114
+ React.createElement(Tooltip, { position: TooltipPosition.top, content: t('Negative feedback') },
115
+ React.createElement("button", { className: "btn btn-app btn-link", onClick: applyCommentFeedback(comment, -1), "data-tracking-id": "case-comment-feedback-down", type: "button" }, feedback === -1 ? (React.createElement(FrownIcon, { title: t('Remove negative feedback'), "aria-label": t('Remove negative feedback') })) : (React.createElement(OutlinedFrownIcon, { title: t('Leave negative feedback'), "aria-label": t('Leave negative feedback') }))))));
101
116
  const computeDiscussionCardCalss = (comment) => {
102
- if (comment.createdByType === 'Associate' && comment.createdBy === 'Automated Support Assistant') {
117
+ if (comment.createdBy === AUTOMATED_SUPPORT_ASSISTANT) {
103
118
  return 'comment-automated';
104
119
  }
105
120
  else if (comment.createdByType === 'Associate') {
@@ -124,8 +139,9 @@ const CaseComments = React.forwardRef((props, ref) => {
124
139
  }
125
140
  };
126
141
  const computeCommentAuthorIcon = (comment) => {
127
- if (comment.createdByType === 'Associate' && comment.createdBy === 'Automated support assistant') {
128
- return (React.createElement("img", { src: "https://static.redhat.com/libs/redhat/brand-assets/2/corp/logo--hat-only.svg", height: "18", width: "18", "aria-hidden": "true", alt: "Automated support assistant comment", title: "Automated support assistant", style: { verticalAlign: '-0.125em', marginRight: '6px' } }));
142
+ if (comment.createdBy === AUTOMATED_SUPPORT_ASSISTANT) {
143
+ return (React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", className: "asa-comment-author-icon", style: { display: 'block', flexShrink: 0, marginRight: '8px' } },
144
+ React.createElement("path", { d: "M6.12207 2.1875C6.35023 2.1875 6.55802 2.38112 6.57617 2.6084C6.78104 5.19193 8.80513 7.2158 11.3887 7.4209C11.6159 7.43885 11.8096 7.64685 11.8096 7.875C11.8096 8.10357 11.6159 8.31072 11.3887 8.3291C8.80515 8.53416 6.78181 10.5585 6.57715 13.1416C6.55879 13.3687 6.35032 13.5625 6.12207 13.5625C5.89427 13.5623 5.6871 13.3688 5.66895 13.1416C5.46407 10.5581 3.4399 8.53431 0.856445 8.3291C0.628957 8.31116 0.435567 8.10314 0.435547 7.875C0.435547 7.64565 0.630491 7.43726 0.859375 7.4209C3.43949 7.21584 5.46331 5.19153 5.66797 2.6084C5.68628 2.38137 5.89416 2.1877 6.12207 2.1875ZM6.12305 4.47754C5.50484 6.02837 4.27607 7.25674 2.72461 7.875C4.27677 8.49323 5.50406 9.72157 6.12207 11.2725C6.7403 9.72157 7.96918 8.49323 9.52051 7.875C7.96835 7.25677 6.74106 6.02843 6.12305 4.47754ZM10.9365 0.654297C11.0628 0.654455 11.1709 0.745742 11.1943 0.87207C11.373 1.84914 12.1499 2.62611 13.127 2.80469C13.2533 2.8283 13.3447 2.93617 13.3447 3.0625C13.3447 3.18886 13.2533 3.2967 13.127 3.32031C12.1498 3.4989 11.3729 4.27583 11.1943 5.25293C11.1709 5.3793 11.0628 5.47054 10.9365 5.4707C10.8101 5.4707 10.7012 5.37937 10.6777 5.25293C10.4996 4.27597 9.72346 3.49901 8.74609 3.32031C8.61962 3.29682 8.52736 3.18892 8.52734 3.0625C8.52734 2.93606 8.61961 2.82818 8.74609 2.80469C9.72344 2.626 10.4995 1.84901 10.6777 0.87207C10.7012 0.745589 10.8101 0.654297 10.9365 0.654297Z", fill: "#1F1F1F" })));
129
145
  }
130
146
  else if (comment.createdByType === 'Associate') {
131
147
  return (React.createElement("img", { src: "https://static.redhat.com/libs/redhat/brand-assets/2/corp/logo--hat-only.svg", height: "18", width: "18", "aria-hidden": "true", alt: "Red Hat associate comment", title: "Red Hat associate", style: { verticalAlign: '-0.125em', marginRight: '6px' } }));
@@ -140,19 +156,13 @@ const CaseComments = React.forwardRef((props, ref) => {
140
156
  }
141
157
  };
142
158
  const computeCommentFooter = (comment) => {
143
- if (!props.comment.isPublic && comment.createdBy === 'Automated Support Assistant') {
144
- return React.createElement(Trans, null, "Private automated comment");
145
- }
146
- else if (!props.comment.isPublic) {
159
+ if (!props.comment.isPublic) {
147
160
  return React.createElement(Trans, null, "Private comment");
148
161
  }
149
162
  else if (comment.createdBy === 'Automated Support Assistant') {
150
163
  return React.createElement(Trans, null, "Automated comment");
151
164
  }
152
165
  };
153
- // Tags the Quill RTE legitimately produces — everything else was typed
154
- // literally by the user or injected from an external source (SFDC) and
155
- // should render as visible text, not interpreted as HTML formatting.
156
166
  const QUILL_TAGS = new Set([
157
167
  'p',
158
168
  'br',
@@ -192,19 +202,13 @@ const CaseComments = React.forwardRef((props, ref) => {
192
202
  const commentText = (text) => {
193
203
  return { __html: sanitizeHtml(text) };
194
204
  };
195
- // Transforms <strong> and <em> tags in HTML string to styled <span> tags to fix incorrect bold/italic rendering in exported PDF
196
205
  function formatMarkdownHtmlForPDF(htmlString) {
197
- return (htmlString
198
- // Handle nested <strong><em>...</em></strong> or <em><strong>...</strong></em> and apply both bold and italic (skew) styles
206
+ return htmlString
199
207
  .replace(/<(strong|em)>\s*<(em|strong)>(.*?)<\/\2>\s*<\/\1>/gi, '<span style="font-weight: bold; font-size: 0.95em; font-style: italic;">$3</span>')
200
- // Handle standalone <strong>
201
208
  .replace(/<strong>(.*?)<\/strong>/gi, '<span style="font-weight: bold; font-size: 0.95em; margin-right: -10px;">$1</span>')
202
- // Handle standalone <em>
203
209
  .replace(/<em>(.*?)<\/em>/gi, '<span style="font-style: italic;font-size: 0.95em; opacity: 0.70;margin-right: 7px;">$1</span>')
204
- // Replace list items with dash bullets
205
210
  .replace(/<li>(.*?)<\/li>/gi, '<div style="margin-left: 1.2em;">- $1</div>')
206
- // Remove <ul> and </ul> tags completely
207
- .replace(/<\/?ul>/gi, ''));
211
+ .replace(/<\/?ul>/gi, '');
208
212
  }
209
213
  const onCommentAreaClick = (e) => {
210
214
  let { event } = e.target['dataset'];
@@ -222,7 +226,6 @@ const CaseComments = React.forwardRef((props, ref) => {
222
226
  const parseCommentHtml = (commentText, contentType) => {
223
227
  let text = commentText;
224
228
  if (contentType === 'plaintext') {
225
- // Legacy plain-text comments: normalize SFDC HTML line breaks
226
229
  text = text
227
230
  .replace(/<br\s*\/?>/gi, '\n')
228
231
  .replace(/<\/p>/gi, '\n')
@@ -238,12 +241,10 @@ const CaseComments = React.forwardRef((props, ref) => {
238
241
  const computeCommentText = (comment) => {
239
242
  if (isEmpty(comment.commentBody))
240
243
  return null;
241
- // Legacy plain-text comments still need escaping and linkification
242
244
  if (comment.contentType === 'plaintext') {
243
245
  const parseComment = parseCommentHtml(comment.commentBody, comment.contentType);
244
246
  return (React.createElement("pre", { className: "push-top-narrow comment-plaintext reset-pre-text", dangerouslySetInnerHTML: commentText(parseComment), style: { fontFamily: isExportingPDF ? 'DejaVu Sans' : '' } }));
245
247
  }
246
- // HTML comments (new rich text or legacy markdown — both stored as HTML)
247
248
  let htmlString = comment.commentBody;
248
249
  htmlString = linkifyHtmlTextNodes(htmlString);
249
250
  if (isExportingPDF) {
@@ -261,28 +262,34 @@ const CaseComments = React.forwardRef((props, ref) => {
261
262
  });
262
263
  }
263
264
  }, [props.comment, isExportingPDF]);
264
- if (!((_a = props.comment) === null || _a === void 0 ? void 0 : _a.isPublic) && !canSeePrivateComments)
265
+ if (!((_b = props.comment) === null || _b === void 0 ? void 0 : _b.isPublic) && !canSeePrivateComments)
265
266
  return React.createElement(React.Fragment, null);
266
267
  return (React.createElement("article", { ref: ref, id: props.comment.id, "aria-label": `Comment by ${props.comment.lastModifiedById}`, className: `prevent-split ${computePrivateComment(props.comment)} support-comment ${computeDiscussionCardCalss(props.comment)} ${ref ? 'selected-case-comment' : ''}` },
267
268
  React.createElement("header", null,
268
269
  React.createElement("h4", null,
269
- computeCommentAuthorIcon(props.comment),
270
- " ",
271
- props.comment.lastModifiedById,
270
+ isAsaComment ? (React.createElement("span", { className: "asa-comment-author" },
271
+ computeCommentAuthorIcon(props.comment),
272
+ React.createElement("span", null, props.comment.createdBy))) : (React.createElement(React.Fragment, null,
273
+ computeCommentAuthorIcon(props.comment),
274
+ props.comment.createdBy)),
272
275
  props.comment.createdByType === 'Partner' && (React.createElement("span", null,
273
276
  ' ',
274
277
  "(",
275
278
  React.createElement(Trans, null, "Partner"),
276
279
  ")"))),
277
280
  React.createElement("time", null, formatDateTime(props.comment.lastModifiedDate))),
281
+ isAsaComment && (React.createElement(Alert, { className: `asa-comment-alert ${isExportingPDF ? 'hide-in-pdf' : ''}`, isInline: true, variant: "custom", title: t('Always review AI-Generated content prior to use') })),
278
282
  React.createElement("div", { className: "comment-body", onClick: onCommentAreaClick, ref: markdownRef }, computeCommentText(props.comment)),
279
283
  React.createElement("footer", null,
280
284
  React.createElement("span", { className: "comment-note" }, computeCommentFooter(props.comment)),
285
+ canSeeFeedbackButtons && commentFeedbackButtons(props.comment, props.feedback),
281
286
  React.createElement("span", { className: "pull-right pf-v6-l-flex pf-m-align-items-center" },
282
287
  props.showJumpToComment && (React.createElement(DiscussionItemLink, { onClick: onJumpToComment(props.comment.id), discussionType: DiscussionType.COMMENT, itemId: props.comment.id, caseNumber: caseNumber, isCopyLink: false },
283
288
  React.createElement(Trans, null, "Jump to comment"))),
284
- React.createElement("button", { onClick: () => props.onReply(props.comment.lastModifiedById, props.comment.id, props.comment.lastModifiedDate), className: `btn btn-app btn-link case-reply-button ${isExportingPDF ? 'hide-in-pdf' : ''}`, "data-tracking-id": "case-comment-reply", type: "button" },
285
- React.createElement(Trans, null, "Reply")),
286
- React.createElement(JumpAndCopyLink, { caseNumber: caseNumber, cardId: props.comment.id, discussionType: DiscussionType.COMMENT })))));
289
+ isAsaComment ? (React.createElement(Button, { variant: ButtonVariant.link, isInline: true, className: `asa-send-feedback-link ${isExportingPDF ? 'hide-in-pdf' : ''}`, onClick: openAsaFeedbackModal, "data-tracking-id": "case-asa-comment-send-feedback-footer" },
290
+ React.createElement(Trans, null, "Send feedback"))) : (React.createElement("button", { onClick: () => props.onReply(props.comment.lastModifiedById, props.comment.id, props.comment.lastModifiedDate), className: `btn btn-app btn-link case-reply-button ${isExportingPDF ? 'hide-in-pdf' : ''}`, "data-tracking-id": "case-comment-reply", type: "button" },
291
+ React.createElement(Trans, null, "Reply"))),
292
+ React.createElement(JumpAndCopyLink, { caseNumber: caseNumber, cardId: props.comment.id, discussionType: DiscussionType.COMMENT }))),
293
+ isAsaComment && (React.createElement(AsaCommentFeedbackModal, { isOpen: isAsaFeedbackModalOpen, isSubmitting: isFeedbackUpdating, initialFeedback: savedFeedbackValue, initialFeedbackReason: savedFeedbackReason, onClose: () => setIsAsaFeedbackModalOpen(false), onSubmit: onSubmitAsaFeedback }))));
287
294
  });
288
295
  export default CaseComments;
@@ -1 +1 @@
1
- {"version":3,"file":"CaseDiscussion.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAqBvE,OAAO,KAA0F,MAAM,OAAO,CAAC;AAyC/G,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;IAC/C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAAK,EAAE,MAAM,qBAy2BnD"}
1
+ {"version":3,"file":"CaseDiscussion.d.ts","sourceRoot":"","sources":["../../../../../../src/components/CaseEditView/Tabs/CaseDiscussion/CaseDiscussion.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAqBvE,OAAO,KAA0F,MAAM,OAAO,CAAC;AA2C/G,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;IAC/C,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CACjD;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAAK,EAAE,MAAM,qBA83BnD"}
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { useApolloClient } from '@apollo/client/react';
11
- import { Button, MenuToggle, Select, SelectList, SelectOption } from '@patternfly/react-core';
11
+ import { Alert, Button, MenuToggle, Select, SelectList, SelectOption } from '@patternfly/react-core';
12
12
  import { AlertMessage, AlertType, ErrorBoundary, LoadingIndicator, ToastNotification } from '@rh-support/components';
13
13
  import { useGlobalStateContext } from '@rh-support/react-context';
14
14
  import { AbilityContext, CaseDetailsFields, resourceActions, resources } from '@rh-support/user-permissions';
@@ -29,19 +29,18 @@ import { useCaseDispatch, useCaseSelector } from '../../../../context/CaseContex
29
29
  import { useCaseDetailsPageDispatchContext, useCaseDetailsPageStateContext, } from '../../../../context/CaseDetailsPageContext';
30
30
  import { useCaseDiscussionTabDispatchContext, useCaseDiscussionTabStateContext, } from '../../../../context/CaseDiscussionTabContext';
31
31
  import { CaseDetailsConstants } from '../../../../reducers/CaseDetailsPageReducer';
32
- import { clearReplyingTo, discussionSortOrderConst, DiscussionType, setDiscussions, setFilter, setReplyingTo, setSort, updateAttachment, updateAttacmentsAfterRemoval, updateDiscussionStateAttachments, } from '../../../../reducers/CaseDiscussionTabReducer';
32
+ import { clearReplyingTo, commputeFeedback, computeFeedbackReason, discussionSortOrderConst, DiscussionType, setDiscussions, setFilter, setReplyingTo, setSort, updateAttachment, updateAttacmentsAfterRemoval, updateDiscussionStateAttachments, } from '../../../../reducers/CaseDiscussionTabReducer';
33
33
  import { setCaseState } from '../../../../reducers/CaseReducer';
34
34
  import { AttachmentContextProvider } from '../../../shared/fileUpload/reducer/AttachmentReducerContext';
35
35
  import { PDFContext } from '../../PDFContainer';
36
36
  import CaseAttachment from './CaseAttachment';
37
- import CaseComments from './CaseComments';
37
+ import CaseComments, { AUTOMATED_SUPPORT_ASSISTANT } from './CaseComments';
38
38
  // import CaseExternalTrackerUpdate from './CaseExternalTrackerUpdate';
39
39
  import { CommentSearch } from './CommentSearch';
40
40
  import { PostComment } from './PostComment';
41
41
  /** Threshold above which comments render in a virtualized (windowed) list for performance. */
42
42
  const VC_MINIMUM_COMMENT = 150;
43
43
  export default function CaseDiscussion(props) {
44
- var _a;
45
44
  const { t } = useTranslation();
46
45
  const { isPostingRemoteRequestCommentCompleted, product, version, caseSalesforceId } = useCaseSelector((state) => ({
47
46
  isPostingRemoteRequestCommentCompleted: state.isPostingRemoteRequestCommentCompleted,
@@ -55,7 +54,7 @@ export default function CaseDiscussion(props) {
55
54
  const { sort, discussionFiltersListState, replyingToAuthor, replyingToTimestamp } = useCaseDiscussionTabStateContext();
56
55
  const { globalMetadataState: { navBarRef, loggedInUsersAccount }, } = useGlobalStateContext();
57
56
  const dispatchDiscussion = useCaseDiscussionTabDispatchContext();
58
- const { caseDetailsPageState: { caseAttachmentHydra }, } = useCaseDetailsPageStateContext();
57
+ const { caseDetailsPageState: { caseAttachmentHydra, caseFeedbacksHydra }, } = useCaseDetailsPageStateContext();
59
58
  const dispatchCaseDetailsHydraAttachments = useCaseDetailsPageDispatchContext();
60
59
  const caseDispatch = useCaseDispatch();
61
60
  const apolloClient = useApolloClient();
@@ -81,6 +80,7 @@ export default function CaseDiscussion(props) {
81
80
  const [selectedFilterItems, setSelectedFilterItems] = useState([]);
82
81
  const [isSortOpen, setIsSortOpen] = useState(false);
83
82
  const [sortSelected, setSortSelected] = useState('Select a value');
83
+ const [localFeedbackOverrides, setLocalFeedbackOverrides] = useState({});
84
84
  const { hasNextPage, isLoadingMore, loadMoreError, fetchMore } = props;
85
85
  const isCommentFilterActive = discussionFiltersListState.some((f) => (f.value === DiscussionType.COMMENT || f.value === DiscussionType.ALL) && f.isSelected);
86
86
  useEffect(() => {
@@ -111,13 +111,20 @@ export default function CaseDiscussion(props) {
111
111
  const cellMeasureCache = cellMeasureCacheRef.current;
112
112
  const allDiscussions = useMemo(() => {
113
113
  var _a, _b, _c;
114
+ const feedbacks = caseFeedbacksHydra.data || [];
114
115
  const allComments = (props.caseComments || [])
115
116
  .filter((comment) => comment.isDraft === false)
116
- .map((comment) => ({
117
- item: Object.assign(Object.assign({}, comment), { isPublic: comment.isPublic === undefined ? true : comment.isPublic, last_modified_date: comment.lastModifiedDate || comment.createdDate }),
118
- discussionType: DiscussionType.COMMENT,
119
- last_modified_date: comment.lastModifiedDate || comment.createdDate,
120
- }));
117
+ .map((comment) => {
118
+ var _a, _b;
119
+ const localOverride = localFeedbackOverrides[comment.id];
120
+ return {
121
+ item: Object.assign(Object.assign({}, comment), { isPublic: comment.isPublic === undefined ? true : comment.isPublic, last_modified_date: comment.lastModifiedDate || comment.createdDate }),
122
+ discussionType: DiscussionType.COMMENT,
123
+ last_modified_date: comment.lastModifiedDate || comment.createdDate,
124
+ feedback: (_a = localOverride === null || localOverride === void 0 ? void 0 : localOverride.feedback) !== null && _a !== void 0 ? _a : commputeFeedback(comment.id, feedbacks),
125
+ feedbackReason: (_b = localOverride === null || localOverride === void 0 ? void 0 : localOverride.feedbackReason) !== null && _b !== void 0 ? _b : computeFeedbackReason(comment.id, feedbacks),
126
+ };
127
+ });
121
128
  let allAttachments = canSeeAttachments
122
129
  ? (caseAttachmentHydra.data || [])
123
130
  .filter((attachment) => (attachment === null || attachment === void 0 ? void 0 : attachment.lastModifiedDate) || (attachment === null || attachment === void 0 ? void 0 : attachment.createdDate))
@@ -143,12 +150,21 @@ export default function CaseDiscussion(props) {
143
150
  }
144
151
  const merged = [...allComments, ...allAttachments];
145
152
  return orderBy(merged, ['last_modified_date', (d) => { var _a; return (_a = d.item.id) !== null && _a !== void 0 ? _a : ''; }], [(_b = sort === null || sort === void 0 ? void 0 : sort.sortOrder) !== null && _b !== void 0 ? _b : 'desc', (_c = sort === null || sort === void 0 ? void 0 : sort.sortOrder) !== null && _c !== void 0 ? _c : 'desc']);
146
- }, [props.caseComments, caseAttachmentHydra.data, canSeeAttachments, sort, props.hasNextPage]);
153
+ }, [
154
+ props.caseComments,
155
+ caseAttachmentHydra.data,
156
+ caseFeedbacksHydra.data,
157
+ localFeedbackOverrides,
158
+ canSeeAttachments,
159
+ sort,
160
+ props.hasNextPage,
161
+ ]);
147
162
  const usedPaginationRef = useRef(false);
148
163
  if (props.hasNextPage || props.isLoadingMore) {
149
164
  usedPaginationRef.current = true;
150
165
  }
151
166
  const shouldRenderRVComponent = !isExportingPDF && allDiscussions.length > VC_MINIMUM_COMMENT && !usedPaginationRef.current;
167
+ const hasAsaComment = (props.caseComments || []).some((comment) => (comment === null || comment === void 0 ? void 0 : comment.createdBy) === AUTOMATED_SUPPORT_ASSISTANT);
152
168
  const list = discussionFiltersListState.filter((f) => f.canSee);
153
169
  const computeFilterComment = () => {
154
170
  return filter(allDiscussions, (discussion) => {
@@ -164,21 +180,6 @@ export default function CaseDiscussion(props) {
164
180
  const isSearchResultEmpty = !isRefetching &&
165
181
  !isEmpty(searchCommentText) &&
166
182
  (searchResult.length === 0 || comuteSearchedComments.length === 0);
167
- // DEBUG: track every render of CaseDiscussion
168
- console.log('[CaseDiscussion] render', {
169
- commentsLoading: props.commentsLoading,
170
- isLoadingMore: props.isLoadingMore,
171
- hasNextPage: props.hasNextPage,
172
- loadMoreError: props.loadMoreError,
173
- isRefetching,
174
- isSearchResultEmpty,
175
- allDiscussionsLen: allDiscussions.length,
176
- filteredLen: computeFilteredComments.length,
177
- searchedLen: comuteSearchedComments.length,
178
- caseCommentsLen: (_a = props.caseComments) === null || _a === void 0 ? void 0 : _a.length,
179
- inView,
180
- isCommentFilterActive,
181
- });
182
183
  const setVRCommentIndex = (cId) => {
183
184
  setCommentIndex(cId < 0 ? 0 : cId);
184
185
  setJumpToCommentClicked(true);
@@ -247,14 +248,25 @@ export default function CaseDiscussion(props) {
247
248
  useEffect(() => {
248
249
  if (isExportingPDF)
249
250
  return;
250
- setDiscussions(dispatchDiscussion, props.caseComments, [], caseAttachmentHydra.data, [], [], discussionFiltersListState, false, false, canSeeAttachments, sort);
251
+ if (caseAttachmentHydra.isFetching || caseFeedbacksHydra.isFetching)
252
+ return;
253
+ setDiscussions(dispatchDiscussion, props.caseComments, [], caseAttachmentHydra.data, caseFeedbacksHydra.data, [], discussionFiltersListState, false, false, canSeeAttachments, sort);
251
254
  // eslint-disable-next-line react-hooks/exhaustive-deps
252
- }, [props.caseComments, caseAttachmentHydra, canSeeAttachments, sort]);
255
+ }, [props.caseComments, caseAttachmentHydra, caseFeedbacksHydra, canSeeAttachments, sort]);
253
256
  useEffect(() => {
254
257
  if (!caseAttachmentHydra.isFetching && caseAttachmentHydra.isError) {
255
258
  ToastNotification.addDangerMessage(t('There was an error loading attachments.'));
256
259
  }
257
- }, [caseAttachmentHydra.isFetching, caseAttachmentHydra.isError, t]);
260
+ if (!caseFeedbacksHydra.isFetching && caseFeedbacksHydra.isError) {
261
+ ToastNotification.addDangerMessage(t('There was an error loading feedback.'));
262
+ }
263
+ }, [
264
+ caseAttachmentHydra.isFetching,
265
+ caseAttachmentHydra.isError,
266
+ caseFeedbacksHydra.isFetching,
267
+ caseFeedbacksHydra.isError,
268
+ t,
269
+ ]);
258
270
  const onCommentAdded = () => __awaiter(this, void 0, void 0, function* () {
259
271
  try {
260
272
  yield props.refetchComments();
@@ -264,6 +276,9 @@ export default function CaseDiscussion(props) {
264
276
  }
265
277
  dtmTrackEventCaseStepEncountered('comment', caseNumber, product, version);
266
278
  });
279
+ const onFeedbackUpdate = (comment_id, feedback, feedbackReason) => {
280
+ setLocalFeedbackOverrides((prev) => (Object.assign(Object.assign({}, prev), { [comment_id]: { feedback, feedbackReason } })));
281
+ };
267
282
  const onReply = (author, commentId, timestamp) => {
268
283
  setReplyingTo(dispatchDiscussion, author, commentId, timestamp);
269
284
  scrollIntoView(props.tabRef, { navBarRef, timeout: 0, onlyIfNotInViewport: true, offset: 30 });
@@ -386,7 +401,7 @@ export default function CaseDiscussion(props) {
386
401
  if (isEmpty(discussion) || isEmpty(discussion.item))
387
402
  return null;
388
403
  return (React.createElement("div", { "data-tracking-id": "discussion-elements", key: discussion.item.id },
389
- discussion.discussionType === DiscussionType.COMMENT && (React.createElement(CaseComments, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, comment: discussion.item, onFeedBackUpdate: () => { }, feedback: discussion.feedback, accountNumber: props.accountNumber, onReply: onReply, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment, downloadAttachment: downloadAttachment })),
404
+ discussion.discussionType === DiscussionType.COMMENT && (React.createElement(CaseComments, { caseNumber: caseNumber, ref: discussionIdFromUrl === discussion.item.id ? activeDiscussionElementRef : null, comment: discussion.item, onFeedBackUpdate: onFeedbackUpdate, feedback: discussion.feedback, feedbackReason: discussion.feedbackReason, accountNumber: props.accountNumber, onReply: onReply, showJumpToComment: !isEmpty(searchCommentText), onJumpToComment: onJumpToComment, downloadAttachment: downloadAttachment })),
390
405
  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 }))));
391
406
  };
392
407
  const rowRenderer = ({ index, parent, key, style, }) => {
@@ -482,28 +497,11 @@ export default function CaseDiscussion(props) {
482
497
  };
483
498
  const onSortToggle = (toggleRef) => (React.createElement(MenuToggle, { ref: toggleRef, onClick: onSortToggleClick, isExpanded: isSortOpen, isFullWidth: true }, sort.name));
484
499
  return (React.createElement(React.Fragment, null,
485
- (() => {
486
- const showInitialLoading = props.commentsLoading && allDiscussions.length === 0;
487
- const showNoComments = !props.commentsLoading && !props.commentsError && allDiscussions.length === 0;
488
- const showDiscussions = allDiscussions.length !== 0;
489
- const showSkeleton = debouncedShowSkeleton;
490
- const showNoMore = !props.hasNextPage &&
491
- !props.isLoadingMore &&
492
- !props.commentsLoading &&
493
- !props.loadMoreError &&
494
- comuteSearchedComments.length > 0;
495
- console.log('[CaseDiscussion] RENDER DECISION', {
496
- showInitialLoading,
497
- showNoComments,
498
- showDiscussions,
499
- isRefetching,
500
- showSkeleton,
501
- showNoMore,
502
- isSearchResultEmpty,
503
- shouldRenderRVComponent,
504
- });
505
- return null;
506
- })(),
500
+ hasAsaComment && (React.createElement(Alert, { className: `asa-discussion-alert ${isExportingPDF ? 'hide-in-pdf' : ''}`, isInline: true, variant: "info", title: t('Important'), "data-tracking-id": "case-discussion-asa-notice" },
501
+ React.createElement(Trans, null,
502
+ "This feature uses AI technology to analyze interactions and provide you with support. Interactions may be used to improve Red Hat products or services. For more information about Red Hat's privacy practices, please refer to the",
503
+ ' ',
504
+ React.createElement("a", { href: "https://www.redhat.com/en/about/privacy-policy", target: "_blank", rel: "noopener noreferrer" }, "Red Hat Privacy Statement")))),
507
505
  React.createElement(ErrorBoundary, { errorMsgInfo: { message: t('There was an error loading post comment section') } },
508
506
  React.createElement(AttachmentContextProvider, null,
509
507
  React.createElement(PostComment, { caseNumber: caseNumber, allDiscussions: allDiscussions, onCommentAdded: onCommentAdded, onAttachmentAdded: onAttachmentAdded, onAttachmentRemove: onAttachmentRemove, replyingToAuthor: replyingToAuthor, replyingToTimestamp: replyingToTimestamp, onClearReply: onClearReply }))),
@@ -114,13 +114,21 @@ button,
114
114
  gap: 8px;
115
115
  font-size: 18px;
116
116
  font-weight: 500;
117
+ line-height: 1.2;
117
118
  }
118
119
 
119
- .support-comment.comment-automated .asa-comment-author-icon {
120
- width: 1rem;
121
- height: 1rem;
120
+ .asa-comment-author {
121
+ display: inline-flex;
122
+ align-items: center;
123
+ min-width: 0;
124
+ }
125
+
126
+ .asa-comment-author-icon {
127
+ width: 16px;
128
+ height: 16px;
122
129
  flex-shrink: 0;
123
- font-weight: bold;
130
+ display: block;
131
+ margin-right: 8px;
124
132
  }
125
133
 
126
134
  .support-comment.comment-automated .asa-comment-alert.pf-v6-c-alert {
@@ -1 +1 @@
1
- {"version":3,"file":"useCaseComments.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useCaseComments/useCaseComments.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAOvE,OAAO,EAAuB,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IACnC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACzC;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,EAC5B,MAAM,EACN,IAAI,EACJ,OAAO,EACP,KAAK,EACL,UAAU,EACV,KAAK,GACR,EAAE,uBAAuB,GAAG,sBAAsB,CA+GlD"}
1
+ {"version":3,"file":"useCaseComments.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useCaseComments/useCaseComments.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAOvE,OAAO,EAAuB,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IACnC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,OAAO,CAAC;IACvB,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACzC;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,EAC5B,MAAM,EACN,IAAI,EACJ,OAAO,EACP,KAAK,EACL,UAAU,EACV,KAAK,GACR,EAAE,uBAAuB,GAAG,sBAAsB,CAkGlD"}
@@ -28,7 +28,7 @@ function buildCaseCommentsFilter(caseId, publicOnly) {
28
28
  * result so cache-and-network does not refetch and overwrite merged pages.
29
29
  */
30
30
  export function useCaseComments({ caseId, skip, orderBy, first, publicOnly, after, }) {
31
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
31
+ var _a, _b, _c, _d, _e;
32
32
  const canSeePrivateComments = ability.can(resourceActions.PATCH, resources.CASE_COMMENTS, CaseDiscussionFields.VIEW_PRIVATE_COMMENT);
33
33
  const shouldFilterPublicOnly = publicOnly !== null && publicOnly !== void 0 ? publicOnly : !canSeePrivateComments;
34
34
  const clampedFirst = clamp(first !== null && first !== void 0 ? first : DEFAULT_PAGE_SIZE, MIN_FIRST, MAX_FIRST);
@@ -52,18 +52,6 @@ export function useCaseComments({ caseId, skip, orderBy, first, publicOnly, afte
52
52
  const endCursor = (_e = pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.endCursor) !== null && _e !== void 0 ? _e : null;
53
53
  const isLoadingMore = networkStatus === NetworkStatus.fetchMore;
54
54
  const comments = useMemo(() => mapCaseCommentsResponse(data), [data]);
55
- // DEBUG: track every render of the hook
56
- const edgeCount = (_k = (_j = (_h = (_g = (_f = data === null || data === void 0 ? void 0 : data.redhat_support_uiapi) === null || _f === void 0 ? void 0 : _f.query) === null || _g === void 0 ? void 0 : _g.RedHatSupportCaseComment__c) === null || _h === void 0 ? void 0 : _h.edges) === null || _j === void 0 ? void 0 : _j.length) !== null && _k !== void 0 ? _k : 0;
57
- console.log('[useCaseComments] render', {
58
- networkStatus,
59
- loading,
60
- isLoadingMore,
61
- hasNextPage,
62
- endCursor: endCursor === null || endCursor === void 0 ? void 0 : endCursor.slice(0, 20),
63
- edgeCount,
64
- commentsMapped: comments.length,
65
- fetchLocked: fetchLockRef.current,
66
- });
67
55
  const fetchMore = useCallback(() => {
68
56
  if (fetchLockRef.current || !hasNextPage || !endCursor) {
69
57
  console.log('[useCaseComments] fetchMore SKIPPED', {
@@ -10,6 +10,7 @@ export interface IDiscussion {
10
10
  last_modified_date: string;
11
11
  discussionType: string;
12
12
  feedback?: number;
13
+ feedbackReason?: string;
13
14
  }
14
15
  export declare enum DiscussionType {
15
16
  COMMENT = "comment",
@@ -48,10 +49,12 @@ export declare const setSort: (dispatch: DiscussionsReducerDispatchType, sort: I
48
49
  export declare const setReplyingTo: (dispatch: DiscussionsReducerDispatchType, author: string, commentId: string, timestamp: string) => void;
49
50
  export declare const clearReplyingTo: (dispatch: DiscussionsReducerDispatchType) => void;
50
51
  export declare const setFilter: (dispatch: DiscussionsReducerDispatchType, selected: string[], discussionFiltersListState: IFilter[]) => void;
52
+ export declare const commputeFeedback: (commentId: string, feedbacks: ICommentFeedback[]) => number;
53
+ export declare const computeFeedbackReason: (commentId: string, feedbacks: ICommentFeedback[]) => string | undefined;
51
54
  export declare const setDiscussions: (dispatch: DiscussionsReducerDispatchType, comments: ICaseComment[], chats: ICaseChat[], attachments: IAttachment[], feedbacks: ICommentFeedback[], trackerUpdates: Partial<unknown[]>, discussionFiltersListState: IFilter[], canSeeExternalTracker: boolean, canSeeChat: boolean, canSeeAttachments: boolean, sort?: ISort) => void;
52
55
  export declare const appendNewComments: (dispatch: DiscussionsReducerDispatchType, allComments: ICaseComment[], existingDiscussions: IDiscussion[], feedbacks: ICommentFeedback[], sort?: ISort) => void;
53
56
  export declare const updateAttacmentsAfterRemoval: (dispatch: DiscussionsReducerDispatchType, uuid_removed: string, allDiscussions: IDiscussion[], discussionFiltersListState: IFilter[]) => void;
54
- export declare const updateCommentStateFeedback: (dispatch: DiscussionsReducerDispatchType, comment_id: string, newFeedback: any, allDiscussions: IDiscussion[]) => Promise<void>;
57
+ export declare const updateCommentStateFeedback: (dispatch: DiscussionsReducerDispatchType, comment_id: string, newFeedback: any, allDiscussions: IDiscussion[], feedbackReason?: string) => Promise<void>;
55
58
  export declare const updateAttachment: (dispatch: DiscussionsReducerDispatchType, uuid: string, newAttachment: any, allDiscussions: IDiscussion[]) => void;
56
59
  export declare const updateDiscussionStateAttachments: (dispatch: DiscussionsReducerDispatchType, caseNumber: string, allDiscussions: IDiscussion[], sort: ISort, discussionFiltersListState: IFilter[], dispatchCaseDetailsHydraAttachments: any, apolloClient: ApolloQueryClient, caseSalesforceId?: string, includeSecureSupport?: boolean) => Promise<void>;
57
60
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"CaseDiscussionTabReducer.d.ts","sourceRoot":"","sources":["../../../src/reducers/CaseDiscussionTabReducer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CaseDiscussionTabReducer.d.ts","sourceRoot":"","sources":["../../../src/reducers/CaseDiscussionTabReducer.ts"],"names":[],"mappings":"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"}
@@ -132,10 +132,14 @@ export const setFilter = (dispatch, selected, discussionFiltersListState) => {
132
132
  dispatch({ type: DiscussionsConstants.updateDiscussionState, payload: { discussionFiltersListState } });
133
133
  }
134
134
  };
135
- const commputeFeedback = (commentId, feedbacks) => {
135
+ export const commputeFeedback = (commentId, feedbacks) => {
136
136
  const feedback = feedbacks.filter((feedback) => feedback.commentId === commentId);
137
137
  return feedback.length === 0 ? undefined : parseInt(feedback[0].feedback);
138
138
  };
139
+ export const computeFeedbackReason = (commentId, feedbacks) => {
140
+ const feedback = (feedbacks || []).find((item) => item.commentId === commentId);
141
+ return feedback === null || feedback === void 0 ? void 0 : feedback.feedbackReason;
142
+ };
139
143
  export const setDiscussions = (dispatch, comments, chats, attachments, feedbacks,
140
144
  // TODO: Uncomment when External Trackers has a functioning GraphQL endpoint
141
145
  // trackerUpdates: Partial<IExternalTrackerUpdate[]>,
@@ -160,6 +164,7 @@ canSeeExternalTracker, canSeeChat, canSeeAttachments, sort) => {
160
164
  discussionType: DiscussionType.COMMENT,
161
165
  last_modified_date: comment.lastModifiedDate || comment.createdDate,
162
166
  feedback: commputeFeedback(comment.id, feedbacks),
167
+ feedbackReason: computeFeedbackReason(comment.id, feedbacks),
163
168
  }));
164
169
  // TODO: Uncomment when External Trackers has a functioning GraphQL endpoint
165
170
  // const allExternalTrackers: IDiscussion[] = (trackerUpdates || []).map((externalUpdate) => ({
@@ -223,6 +228,7 @@ export const appendNewComments = (dispatch, allComments, existingDiscussions, fe
223
228
  discussionType: DiscussionType.COMMENT,
224
229
  last_modified_date: comment.lastModifiedDate || comment.createdDate,
225
230
  feedback: commputeFeedback(comment.id, feedbacks),
231
+ feedbackReason: computeFeedbackReason(comment.id, feedbacks),
226
232
  }));
227
233
  const sortOrder = (_a = sort === null || sort === void 0 ? void 0 : sort.sortOrder) !== null && _a !== void 0 ? _a : 'desc';
228
234
  const merged = sortOrder === 'desc'
@@ -247,10 +253,13 @@ export const updateAttacmentsAfterRemoval = (dispatch, uuid_removed, allDiscussi
247
253
  dispatch({ type: DiscussionsConstants.updateDiscussionState, payload: { discussionFiltersListState } });
248
254
  dispatch({ type: DiscussionsConstants.updateDiscussionState, payload: { allDiscussions } });
249
255
  };
250
- export const updateCommentStateFeedback = (dispatch, comment_id, newFeedback, allDiscussions) => __awaiter(void 0, void 0, void 0, function* () {
256
+ export const updateCommentStateFeedback = (dispatch, comment_id, newFeedback, allDiscussions, feedbackReason) => __awaiter(void 0, void 0, void 0, function* () {
251
257
  const updateDiscussions = allDiscussions.map((discussion) => {
252
258
  if (discussion.discussionType === DiscussionType.COMMENT && discussion.item.id === comment_id) {
253
259
  discussion.feedback = newFeedback;
260
+ if (feedbackReason !== undefined) {
261
+ discussion.feedbackReason = feedbackReason;
262
+ }
254
263
  }
255
264
  return discussion;
256
265
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rh-support/troubleshoot",
3
- "version": "2.7.10",
3
+ "version": "2.7.12",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org"
@@ -52,11 +52,11 @@
52
52
  "@progress/kendo-licensing": "1.3.5",
53
53
  "@progress/kendo-react-pdf": "^5.16.0",
54
54
  "@redux-devtools/extension": "^3.3.0",
55
- "@rh-support/components": "2.6.10",
56
- "@rh-support/react-context": "2.6.10",
55
+ "@rh-support/components": "2.6.12",
56
+ "@rh-support/react-context": "2.6.12",
57
57
  "@rh-support/types": "2.0.26",
58
58
  "@rh-support/user-permissions": "2.5.170",
59
- "@rh-support/utils": "2.5.149",
59
+ "@rh-support/utils": "2.6.11",
60
60
  "@types/react-redux": "^7.1.33",
61
61
  "@types/redux": "^3.6.0",
62
62
  "date-fns": "3.6.0",
@@ -129,5 +129,5 @@
129
129
  "defaults and supports es6-module",
130
130
  "maintained node versions"
131
131
  ],
132
- "gitHead": "3f16770cee04217483b234f6d8dceaced57a0695"
132
+ "gitHead": "d4bd1a2535f8e53a2fc70ccd7252992b051ba214"
133
133
  }