stacktrace.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import * as React from 'react';
  2. import EventDataSection from 'app/components/events/eventDataSection';
  3. import CrashContent from 'app/components/events/interfaces/crashContent';
  4. import CrashActions from 'app/components/events/interfaces/crashHeader/crashActions';
  5. import CrashTitle from 'app/components/events/interfaces/crashHeader/crashTitle';
  6. import {t} from 'app/locale';
  7. import ConfigStore from 'app/stores/configStore';
  8. import {Group, Project} from 'app/types';
  9. import {Event} from 'app/types/event';
  10. import {STACK_TYPE, STACK_VIEW} from 'app/types/stacktrace';
  11. import NoStackTraceMessage from './noStackTraceMessage';
  12. export function isStacktraceNewestFirst() {
  13. const user = ConfigStore.get('user');
  14. // user may not be authenticated
  15. if (!user) {
  16. return true;
  17. }
  18. switch (user.options.stacktraceOrder) {
  19. case 2:
  20. return true;
  21. case 1:
  22. return false;
  23. case -1:
  24. default:
  25. return true;
  26. }
  27. }
  28. const defaultProps = {
  29. hideGuide: false,
  30. };
  31. type CrashContentProps = React.ComponentProps<typeof CrashContent>;
  32. type Props = Pick<CrashContentProps, 'groupingCurrentLevel' | 'hasGroupingTreeUI'> & {
  33. event: Event;
  34. type: string;
  35. data: NonNullable<CrashContentProps['stacktrace']>;
  36. projectId: Project['id'];
  37. hasGroupingTreeUI: boolean;
  38. groupingCurrentLevel?: Group['metadata']['current_level'];
  39. hideGuide?: boolean;
  40. } & typeof defaultProps;
  41. type State = {
  42. stackView: STACK_VIEW;
  43. newestFirst: boolean;
  44. };
  45. class StacktraceInterface extends React.Component<Props, State> {
  46. static defaultProps = defaultProps;
  47. state: State = {
  48. stackView: this.props.data.hasSystemFrames ? STACK_VIEW.APP : STACK_VIEW.FULL,
  49. newestFirst: isStacktraceNewestFirst(),
  50. };
  51. handleChangeNewestFirst = ({newestFirst}: Pick<State, 'newestFirst'>) => {
  52. this.setState(prevState => ({...prevState, newestFirst}));
  53. };
  54. handleChangeStackView = ({
  55. stackView,
  56. }: Parameters<
  57. NonNullable<React.ComponentProps<typeof CrashActions>['onChange']>
  58. >[0]) => {
  59. if (!stackView) {
  60. return;
  61. }
  62. this.setState(prevState => ({...prevState, stackView}));
  63. };
  64. render() {
  65. const {
  66. projectId,
  67. event,
  68. data,
  69. hideGuide,
  70. type,
  71. groupingCurrentLevel,
  72. hasGroupingTreeUI,
  73. } = this.props;
  74. const {stackView, newestFirst} = this.state;
  75. const stackTraceNotFound = !(data.frames ?? []).length;
  76. return (
  77. <EventDataSection
  78. type={type}
  79. title={
  80. <CrashTitle
  81. title={t('Stack Trace')}
  82. hideGuide={hideGuide}
  83. newestFirst={newestFirst}
  84. onChange={!stackTraceNotFound ? this.handleChangeNewestFirst : undefined}
  85. />
  86. }
  87. actions={
  88. !stackTraceNotFound && (
  89. <CrashActions
  90. stackView={stackView}
  91. platform={event.platform}
  92. stacktrace={data}
  93. hasGroupingTreeUI={hasGroupingTreeUI}
  94. onChange={this.handleChangeStackView}
  95. />
  96. )
  97. }
  98. wrapTitle={false}
  99. >
  100. {stackTraceNotFound ? (
  101. <NoStackTraceMessage />
  102. ) : (
  103. <CrashContent
  104. projectId={projectId}
  105. event={event}
  106. stackView={stackView}
  107. newestFirst={newestFirst}
  108. stacktrace={data}
  109. stackType={STACK_TYPE.ORIGINAL}
  110. groupingCurrentLevel={groupingCurrentLevel}
  111. hasGroupingTreeUI={hasGroupingTreeUI}
  112. />
  113. )}
  114. </EventDataSection>
  115. );
  116. }
  117. }
  118. export default StacktraceInterface;