index.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import {useState} from 'react';
  2. import KeyValueList from 'sentry/components/events/interfaces/keyValueList';
  3. import {SegmentedControl} from 'sentry/components/segmentedControl';
  4. import {t} from 'sentry/locale';
  5. import type {Event} from 'sentry/types/event';
  6. import {EntryType} from 'sentry/types/event';
  7. import {FoldSectionKey} from 'sentry/views/issueDetails/streamline/foldSection';
  8. import {InterimSection} from 'sentry/views/issueDetails/streamline/interimSection';
  9. import type {HelpProps} from './help';
  10. import Help from './help';
  11. type View = 'report' | 'raw' | 'help';
  12. function getView(view: View, data: Record<any, any>, meta: Record<any, any>) {
  13. switch (view) {
  14. case 'report':
  15. return (
  16. <KeyValueList
  17. data={Object.entries(data).map(([key, value]) => {
  18. return {
  19. key,
  20. subject: key,
  21. value,
  22. meta: meta?.[key]?.[''],
  23. };
  24. })}
  25. isContextData
  26. />
  27. );
  28. case 'raw':
  29. return <pre>{JSON.stringify({'csp-report': data}, null, 2)}</pre>;
  30. case 'help':
  31. return <Help data={data as HelpProps['data']} />;
  32. default:
  33. throw new TypeError(`Invalid view: ${view}`);
  34. }
  35. }
  36. type Props = {
  37. data: Record<string, any>;
  38. event: Event;
  39. };
  40. export function Csp({data, event}: Props) {
  41. const [view, setView] = useState<View>('report');
  42. const entryIndex = event.entries.findIndex(entry => entry.type === EntryType.CSP);
  43. const meta = event._meta?.entries?.[entryIndex]?.data;
  44. const cleanData =
  45. data.original_policy !== 'string'
  46. ? data
  47. : {
  48. ...data,
  49. // Hide the report-uri since this is redundant and silly
  50. original_policy: data.original_policy.replace(/(;\s+)?report-uri [^;]+/, ''),
  51. };
  52. const actions = (
  53. <SegmentedControl aria-label={t('View')} size="xs" value={view} onChange={setView}>
  54. <SegmentedControl.Item key="report">{t('Report')}</SegmentedControl.Item>
  55. <SegmentedControl.Item key="raw">{t('Raw')}</SegmentedControl.Item>
  56. <SegmentedControl.Item key="help">{t('Help')}</SegmentedControl.Item>
  57. </SegmentedControl>
  58. );
  59. return (
  60. <InterimSection title={t('CSP Report')} actions={actions} type={FoldSectionKey.CSP}>
  61. {getView(view, cleanData, meta)}
  62. </InterimSection>
  63. );
  64. }