keyTransactionButton.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import {Component} from 'react';
  2. import {toggleKeyTransaction} from 'app/actionCreators/performance';
  3. import {Client} from 'app/api';
  4. import Button from 'app/components/button';
  5. import {IconStar} from 'app/icons';
  6. import {t} from 'app/locale';
  7. import {Organization} from 'app/types';
  8. import {trackAnalyticsEvent} from 'app/utils/analytics';
  9. import EventView from 'app/utils/discover/eventView';
  10. import withApi from 'app/utils/withApi';
  11. type Props = {
  12. api: Client;
  13. eventView: EventView;
  14. organization: Organization;
  15. transactionName: string;
  16. };
  17. type State = {
  18. isLoading: boolean;
  19. keyFetchID: symbol | undefined;
  20. error: null | string;
  21. isKeyTransaction: boolean;
  22. };
  23. class KeyTransactionButton extends Component<Props, State> {
  24. state: State = {
  25. isLoading: true,
  26. keyFetchID: undefined,
  27. error: null,
  28. isKeyTransaction: false,
  29. };
  30. componentDidMount() {
  31. this.fetchData();
  32. }
  33. componentDidUpdate(prevProps: Props) {
  34. const orgSlugChanged = prevProps.organization.slug !== this.props.organization.slug;
  35. const projectsChanged =
  36. prevProps.eventView.project.length === 1 &&
  37. this.props.eventView.project.length === 1 &&
  38. prevProps.eventView.project[0] !== this.props.eventView.project[0];
  39. if (orgSlugChanged || projectsChanged) {
  40. this.fetchData();
  41. }
  42. }
  43. fetchData = () => {
  44. const {organization, eventView, transactionName} = this.props;
  45. const projects = eventView.project as number[];
  46. if (projects.length !== 1) {
  47. return;
  48. }
  49. const url = `/organizations/${organization.slug}/is-key-transactions/`;
  50. const keyFetchID = Symbol('keyFetchID');
  51. this.setState({isLoading: true, keyFetchID});
  52. this.props.api
  53. .requestPromise(url, {
  54. method: 'GET',
  55. includeAllArgs: true,
  56. query: {
  57. project: projects.map(id => String(id)),
  58. transaction: transactionName,
  59. },
  60. })
  61. .then(([data, _, _jqXHR]) => {
  62. if (this.state.keyFetchID !== keyFetchID) {
  63. // invariant: a different request was initiated after this request
  64. return;
  65. }
  66. this.setState({
  67. isLoading: false,
  68. keyFetchID: undefined,
  69. error: null,
  70. isKeyTransaction: !!data?.isKey,
  71. });
  72. })
  73. .catch(err => {
  74. this.setState({
  75. isLoading: false,
  76. keyFetchID: undefined,
  77. error: err.responseJSON?.detail ?? null,
  78. isKeyTransaction: false,
  79. });
  80. });
  81. };
  82. toggleKeyTransactionHandler = () => {
  83. const {eventView, api, organization, transactionName} = this.props;
  84. const {isKeyTransaction} = this.state;
  85. const projects = eventView.project.map(String);
  86. trackAnalyticsEvent({
  87. eventName: 'Performance Views: Key Transaction toggle',
  88. eventKey: 'performance_views.key_transaction.toggle',
  89. organization_id: organization.id,
  90. action: isKeyTransaction ? 'remove' : 'add',
  91. });
  92. toggleKeyTransaction(
  93. api,
  94. isKeyTransaction,
  95. organization.slug,
  96. projects,
  97. transactionName
  98. ).then(() => {
  99. this.setState({isKeyTransaction: !isKeyTransaction});
  100. });
  101. };
  102. render() {
  103. const {isKeyTransaction, isLoading} = this.state;
  104. if (this.props.eventView.project.length !== 1 || isLoading) {
  105. return null;
  106. }
  107. return (
  108. <Button
  109. icon={isKeyTransaction ? <IconStar color="yellow300" isSolid /> : <IconStar />}
  110. onClick={this.toggleKeyTransactionHandler}
  111. >
  112. {t('Key Transaction')}
  113. </Button>
  114. );
  115. }
  116. }
  117. export default withApi(KeyTransactionButton);