externalIssueForm.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import * as Sentry from '@sentry/react';
  2. import {addSuccessMessage} from 'sentry/actionCreators/indicator';
  3. import AsyncComponent from 'sentry/components/asyncComponent';
  4. import AbstractExternalIssueForm, {
  5. ExternalIssueAction,
  6. } from 'sentry/components/externalIssues/abstractExternalIssueForm';
  7. import {FormProps} from 'sentry/components/forms/form';
  8. import NavTabs from 'sentry/components/navTabs';
  9. import {t, tct} from 'sentry/locale';
  10. import {Group, Integration, IntegrationExternalIssue} from 'sentry/types';
  11. const MESSAGES_BY_ACTION = {
  12. link: t('Successfully linked issue.'),
  13. create: t('Successfully created issue.'),
  14. };
  15. const SUBMIT_LABEL_BY_ACTION = {
  16. link: t('Link Issue'),
  17. create: t('Create Issue'),
  18. };
  19. type Props = {
  20. group: Group;
  21. integration: Integration;
  22. onChange: (onSuccess?: () => void, onError?: () => void) => void;
  23. } & AbstractExternalIssueForm['props'];
  24. type State = AbstractExternalIssueForm['state'];
  25. export default class ExternalIssueForm extends AbstractExternalIssueForm<Props, State> {
  26. loadTransaction?: ReturnType<typeof Sentry.startTransaction>;
  27. submitTransaction?: ReturnType<typeof Sentry.startTransaction>;
  28. constructor(props) {
  29. super(props, {});
  30. this.loadTransaction = this.startTransaction('load');
  31. }
  32. getEndpoints(): ReturnType<AsyncComponent['getEndpoints']> {
  33. const query: {action?: ExternalIssueAction} = {};
  34. if (this.state?.hasOwnProperty('action')) {
  35. query.action = this.state.action;
  36. }
  37. return [['integrationDetails', this.getEndPointString(), {query}]];
  38. }
  39. handleClick = (action: ExternalIssueAction) => {
  40. this.setState({action}, () => this.reloadData());
  41. };
  42. startTransaction = (type: 'load' | 'submit') => {
  43. const {group, integration} = this.props;
  44. const {action} = this.state;
  45. const transaction = Sentry.startTransaction({name: `externalIssueForm.${type}`});
  46. Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));
  47. transaction.setTag('issueAction', action);
  48. transaction.setTag('groupID', group.id);
  49. transaction.setTag('projectID', group.project.id);
  50. transaction.setTag('integrationSlug', integration.provider.slug);
  51. transaction.setTag('integrationType', 'firstParty');
  52. return transaction;
  53. };
  54. handlePreSubmit = () => {
  55. this.submitTransaction = this.startTransaction('submit');
  56. };
  57. onSubmitSuccess = (_data: IntegrationExternalIssue): void => {
  58. const {onChange, closeModal} = this.props;
  59. const {action} = this.state;
  60. onChange(() => addSuccessMessage(MESSAGES_BY_ACTION[action]));
  61. closeModal();
  62. this.submitTransaction?.finish();
  63. };
  64. handleSubmitError = () => {
  65. this.submitTransaction?.finish();
  66. };
  67. onLoadAllEndpointsSuccess = () => {
  68. this.loadTransaction?.finish();
  69. };
  70. onRequestError = () => {
  71. this.loadTransaction?.finish();
  72. };
  73. getEndPointString() {
  74. const {group, integration} = this.props;
  75. return `/groups/${group.id}/integrations/${integration.id}/`;
  76. }
  77. getTitle = () => {
  78. const {integration} = this.props;
  79. return tct('[integration] Issue', {integration: integration.provider.name});
  80. };
  81. getFormProps = (): FormProps => {
  82. const {action} = this.state;
  83. return {
  84. ...this.getDefaultFormProps(),
  85. submitLabel: SUBMIT_LABEL_BY_ACTION[action],
  86. apiEndpoint: this.getEndPointString(),
  87. apiMethod: action === 'create' ? 'POST' : 'PUT',
  88. onPreSubmit: this.handlePreSubmit,
  89. onSubmitError: this.handleSubmitError,
  90. onSubmitSuccess: this.onSubmitSuccess,
  91. };
  92. };
  93. renderNavTabs = () => {
  94. const {action} = this.state;
  95. return (
  96. <NavTabs underlined>
  97. <li className={action === 'create' ? 'active' : ''}>
  98. <a onClick={() => this.handleClick('create')}>{t('Create')}</a>
  99. </li>
  100. <li className={action === 'link' ? 'active' : ''}>
  101. <a onClick={() => this.handleClick('link')}>{t('Link')}</a>
  102. </li>
  103. </NavTabs>
  104. );
  105. };
  106. renderBody() {
  107. return this.renderForm(this.getCleanedFields());
  108. }
  109. }