keyValueList.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import * as React from 'react';
  2. import styled from '@emotion/styled';
  3. import sortBy from 'lodash/sortBy';
  4. import ContextData from 'sentry/components/contextData';
  5. import AnnotatedText from 'sentry/components/events/meta/annotatedText';
  6. import {KeyValueListData} from 'sentry/types';
  7. import {defined} from 'sentry/utils';
  8. import theme from 'sentry/utils/theme';
  9. type Props = {
  10. data?: KeyValueListData;
  11. onClick?: () => void;
  12. raw?: boolean;
  13. longKeys?: boolean;
  14. isContextData?: boolean;
  15. isSorted?: boolean;
  16. };
  17. const KeyValueList = ({
  18. data,
  19. isContextData = false,
  20. isSorted = true,
  21. raw = false,
  22. longKeys = false,
  23. onClick,
  24. }: Props) => {
  25. if (!defined(data) || data.length === 0) {
  26. return null;
  27. }
  28. const getData = () => {
  29. if (isSorted) {
  30. return sortBy(data, [({key}) => key.toLowerCase()]);
  31. }
  32. return data;
  33. };
  34. return (
  35. <table className="table key-value" onClick={onClick}>
  36. <tbody>
  37. {getData().map(
  38. ({key, subject, value = null, meta, subjectIcon, subjectDataTestId}) => {
  39. const dataValue: React.ReactNode =
  40. typeof value === 'object' && !React.isValidElement(value)
  41. ? JSON.stringify(value, null, 2)
  42. : value;
  43. let contentComponent: React.ReactNode = (
  44. <pre className="val-string">
  45. <AnnotatedText value={dataValue} meta={meta} />
  46. {subjectIcon}
  47. </pre>
  48. );
  49. if (isContextData) {
  50. contentComponent = (
  51. <ContextData
  52. data={!raw ? value : JSON.stringify(value)}
  53. meta={meta}
  54. withAnnotatedText
  55. >
  56. {subjectIcon}
  57. </ContextData>
  58. );
  59. } else if (typeof dataValue !== 'string' && React.isValidElement(dataValue)) {
  60. contentComponent = dataValue;
  61. }
  62. return (
  63. <tr key={key}>
  64. <TableSubject className="key" wide={longKeys}>
  65. {subject}
  66. </TableSubject>
  67. <td className="val" data-test-id={subjectDataTestId}>
  68. {contentComponent}
  69. </td>
  70. </tr>
  71. );
  72. }
  73. )}
  74. </tbody>
  75. </table>
  76. );
  77. };
  78. const TableSubject = styled('td')<{wide?: boolean}>`
  79. @media (min-width: ${theme.breakpoints[2]}) {
  80. max-width: ${p => (p.wide ? '620px !important' : 'none')};
  81. }
  82. `;
  83. KeyValueList.displayName = 'KeyValueList';
  84. export default KeyValueList;