userFeedback.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import styled from '@emotion/styled';
  2. import {ActivityAuthor} from 'sentry/components/activity/author';
  3. import {ActivityItem} from 'sentry/components/activity/item';
  4. import {Button} from 'sentry/components/button';
  5. import Link from 'sentry/components/links/link';
  6. import {IconCopy} from 'sentry/icons';
  7. import {t} from 'sentry/locale';
  8. import {space} from 'sentry/styles/space';
  9. import {UserReport} from 'sentry/types';
  10. import {escape, nl2br} from 'sentry/utils';
  11. import useCopyToClipboard from 'sentry/utils/useCopyToClipboard';
  12. type Props = {
  13. issueId: string;
  14. orgId: string;
  15. report: UserReport;
  16. className?: string;
  17. };
  18. export function EventUserFeedback({className, report, orgId, issueId}: Props) {
  19. const user = report.user || {
  20. name: report.name,
  21. email: report.email,
  22. id: '',
  23. username: '',
  24. ip_address: '',
  25. };
  26. const {onClick, label} = useCopyToClipboard({text: report.email});
  27. return (
  28. <div className={className}>
  29. <StyledActivityItem
  30. date={report.dateCreated}
  31. author={{type: 'user', user}}
  32. header={
  33. <Items>
  34. <ActivityAuthor>{report.name}</ActivityAuthor>
  35. <CopyButton
  36. aria-label={label}
  37. borderless
  38. onClick={onClick}
  39. size="zero"
  40. title={label}
  41. tooltipProps={{delay: 0}}
  42. translucentBorder
  43. icon={<StyledIconCopy size="xs" />}
  44. >
  45. {report.email}
  46. </CopyButton>
  47. {report.eventID && (
  48. <ViewEventLink
  49. to={`/organizations/${orgId}/issues/${issueId}/events/${report.eventID}/?referrer=user-feedback`}
  50. >
  51. {t('View event')}
  52. </ViewEventLink>
  53. )}
  54. </Items>
  55. }
  56. >
  57. <p
  58. dangerouslySetInnerHTML={{
  59. __html: nl2br(escape(report.comments)),
  60. }}
  61. />
  62. </StyledActivityItem>
  63. </div>
  64. );
  65. }
  66. const StyledActivityItem = styled(ActivityItem)`
  67. margin-bottom: 0;
  68. `;
  69. const Items = styled('div')`
  70. display: flex;
  71. align-items: center;
  72. gap: ${space(1)};
  73. `;
  74. const CopyButton = styled(Button)`
  75. color: ${p => p.theme.subText};
  76. font-size: ${p => p.theme.fontSizeSmall};
  77. font-weight: normal;
  78. `;
  79. const StyledIconCopy = styled(IconCopy)``;
  80. const ViewEventLink = styled(Link)`
  81. font-weight: 300;
  82. font-size: 0.9em;
  83. `;