index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import {Component} from 'react';
  2. import {RouteComponentProps} from 'react-router';
  3. import * as qs from 'query-string';
  4. import GroupingActions from 'sentry/actions/groupingActions';
  5. import Alert from 'sentry/components/alert';
  6. import * as Layout from 'sentry/components/layouts/thirds';
  7. import LoadingError from 'sentry/components/loadingError';
  8. import LoadingIndicator from 'sentry/components/loadingIndicator';
  9. import {t} from 'sentry/locale';
  10. import GroupingStore, {Fingerprint} from 'sentry/stores/groupingStore';
  11. import {Group, Organization, Project} from 'sentry/types';
  12. import {callIfFunction} from 'sentry/utils/callIfFunction';
  13. import withOrganization from 'sentry/utils/withOrganization';
  14. import MergedList from './mergedList';
  15. type Props = RouteComponentProps<
  16. {groupId: Group['id']; orgId: Organization['slug']},
  17. {}
  18. > & {
  19. organization: Organization;
  20. project: Project;
  21. };
  22. type State = {
  23. error: boolean;
  24. loading: boolean;
  25. mergedItems: Array<Fingerprint>;
  26. query: string;
  27. mergedLinks?: string;
  28. };
  29. class GroupMergedView extends Component<Props, State> {
  30. state: State = {
  31. mergedItems: [],
  32. loading: true,
  33. error: false,
  34. query: this.props.location.query.query || '',
  35. };
  36. componentDidMount() {
  37. this.fetchData();
  38. }
  39. componentWillReceiveProps(nextProps: Props) {
  40. if (
  41. nextProps.params.groupId !== this.props.params.groupId ||
  42. nextProps.location.search !== this.props.location.search
  43. ) {
  44. const queryParams = nextProps.location.query;
  45. this.setState(
  46. {
  47. query: queryParams.query,
  48. },
  49. this.fetchData
  50. );
  51. }
  52. }
  53. componentWillUnmount() {
  54. callIfFunction(this.listener);
  55. }
  56. onGroupingChange = ({mergedItems, mergedLinks, loading, error}) => {
  57. if (mergedItems) {
  58. this.setState({
  59. mergedItems,
  60. mergedLinks,
  61. loading: typeof loading !== 'undefined' ? loading : false,
  62. error: typeof error !== 'undefined' ? error : false,
  63. });
  64. }
  65. };
  66. listener = GroupingStore.listen(this.onGroupingChange, undefined);
  67. getEndpoint() {
  68. const {params, location} = this.props;
  69. const {groupId} = params;
  70. const queryParams = {
  71. ...location.query,
  72. limit: 50,
  73. query: this.state.query,
  74. };
  75. return `/issues/${groupId}/hashes/?${qs.stringify(queryParams)}`;
  76. }
  77. fetchData = () => {
  78. GroupingActions.fetch([
  79. {
  80. endpoint: this.getEndpoint(),
  81. dataKey: 'merged',
  82. queryParams: this.props.location.query,
  83. },
  84. ]);
  85. };
  86. handleUnmerge = () => {
  87. GroupingActions.unmerge({
  88. groupId: this.props.params.groupId,
  89. loadingMessage: t('Unmerging events\u2026'),
  90. successMessage: t('Events successfully queued for unmerging.'),
  91. errorMessage: t('Unable to queue events for unmerging.'),
  92. });
  93. };
  94. render() {
  95. const {project, params} = this.props;
  96. const {groupId} = params;
  97. const {loading: isLoading, error, mergedItems, mergedLinks} = this.state;
  98. const isError = error && !isLoading;
  99. const isLoadedSuccessfully = !isError && !isLoading;
  100. return (
  101. <Layout.Body>
  102. <Layout.Main fullWidth>
  103. <Alert type="warning">
  104. {t(
  105. 'This is an experimental feature. Data may not be immediately available while we process unmerges.'
  106. )}
  107. </Alert>
  108. {isLoading && <LoadingIndicator />}
  109. {isError && (
  110. <LoadingError
  111. message={t('Unable to load merged events, please try again later')}
  112. onRetry={this.fetchData}
  113. />
  114. )}
  115. {isLoadedSuccessfully && (
  116. <MergedList
  117. project={project}
  118. fingerprints={mergedItems}
  119. pageLinks={mergedLinks}
  120. groupId={groupId}
  121. onUnmerge={this.handleUnmerge}
  122. onToggleCollapse={GroupingActions.toggleCollapseFingerprints}
  123. />
  124. )}
  125. </Layout.Main>
  126. </Layout.Body>
  127. );
  128. }
  129. }
  130. export {GroupMergedView};
  131. export default withOrganization(GroupMergedView);