index.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import {Component} from 'react';
  2. import {RouteComponentProps} from 'react-router';
  3. import styled from '@emotion/styled';
  4. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  5. import EmailField from 'sentry/components/forms/fields/emailField';
  6. import Form from 'sentry/components/forms/form';
  7. import NarrowLayout from 'sentry/components/narrowLayout';
  8. import {IconMegaphone} from 'sentry/icons';
  9. import {t, tct} from 'sentry/locale';
  10. import {space} from 'sentry/styles/space';
  11. import {trackAdhocEvent} from 'sentry/utils/analytics';
  12. type Props = RouteComponentProps<{orgId: string}, {}>;
  13. type State = {
  14. submitSuccess: boolean | null;
  15. };
  16. class OrganizationJoinRequest extends Component<Props, State> {
  17. state: State = {
  18. submitSuccess: null,
  19. };
  20. componentDidMount() {
  21. const {params} = this.props;
  22. trackAdhocEvent({
  23. eventKey: 'join_request.viewed',
  24. org_slug: params.orgId,
  25. });
  26. }
  27. handleSubmitSuccess = () => {
  28. this.setState({submitSuccess: true});
  29. };
  30. handleSubmitError() {
  31. addErrorMessage(t('Request to join failed'));
  32. }
  33. handleCancel = e => {
  34. e.preventDefault();
  35. const {params} = this.props;
  36. window.location.assign(`/auth/login/${params.orgId}/`);
  37. };
  38. render() {
  39. const {params} = this.props;
  40. const {submitSuccess} = this.state;
  41. if (submitSuccess) {
  42. return (
  43. <NarrowLayout maxWidth="550px">
  44. <SuccessModal>
  45. <StyledIconMegaphone size="xxl" />
  46. <StyledHeader>{t('Request Sent')}</StyledHeader>
  47. <StyledText>{t('Your request to join has been sent.')}</StyledText>
  48. <ReceiveEmailMessage>
  49. {t('You will receive an email when your request is approved.')}
  50. </ReceiveEmailMessage>
  51. </SuccessModal>
  52. </NarrowLayout>
  53. );
  54. }
  55. return (
  56. <NarrowLayout maxWidth="650px">
  57. <StyledIconMegaphone size="xxl" />
  58. <StyledHeader data-test-id="join-request">{t('Request to Join')}</StyledHeader>
  59. <StyledText>
  60. {tct('Ask the admins if you can join the [orgId] organization.', {
  61. orgId: params.orgId,
  62. })}
  63. </StyledText>
  64. <Form
  65. requireChanges
  66. apiEndpoint={`/organizations/${params.orgId}/join-request/`}
  67. apiMethod="POST"
  68. submitLabel={t('Request to Join')}
  69. onSubmitSuccess={this.handleSubmitSuccess}
  70. onSubmitError={this.handleSubmitError}
  71. onCancel={this.handleCancel}
  72. >
  73. <StyledEmailField
  74. name="email"
  75. inline={false}
  76. label={t('Email Address')}
  77. placeholder="name@example.com"
  78. />
  79. </Form>
  80. </NarrowLayout>
  81. );
  82. }
  83. }
  84. const SuccessModal = styled('div')`
  85. display: grid;
  86. justify-items: center;
  87. text-align: center;
  88. padding-top: 10px;
  89. padding-bottom: ${space(4)};
  90. `;
  91. const StyledIconMegaphone = styled(IconMegaphone)`
  92. padding-bottom: ${space(3)};
  93. `;
  94. const StyledHeader = styled('h3')`
  95. margin-bottom: ${space(1)};
  96. `;
  97. const StyledText = styled('p')`
  98. margin-bottom: 0;
  99. `;
  100. const ReceiveEmailMessage = styled(StyledText)`
  101. max-width: 250px;
  102. `;
  103. const StyledEmailField = styled(EmailField)`
  104. padding-top: ${space(2)};
  105. padding-left: 0;
  106. `;
  107. export default OrganizationJoinRequest;