integrationServerlessFunctions.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // eslint-disable-next-line simple-import-sort/imports
  2. import {Fragment} from 'react';
  3. import styled from '@emotion/styled';
  4. import AsyncComponent from 'sentry/components/asyncComponent';
  5. import {IntegrationWithConfig, Organization, ServerlessFunction} from 'sentry/types';
  6. import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels';
  7. import space from 'sentry/styles/space';
  8. import Alert from 'sentry/components/alert';
  9. import withOrganization from 'sentry/utils/withOrganization';
  10. import {t} from 'sentry/locale';
  11. import {trackIntegrationAnalytics} from 'sentry/utils/integrationUtil';
  12. import IntegrationServerlessRow from './integrationServerlessRow';
  13. type Props = AsyncComponent['props'] & {
  14. integration: IntegrationWithConfig;
  15. organization: Organization;
  16. };
  17. type State = AsyncComponent['state'] & {
  18. serverlessFunctions: ServerlessFunction[];
  19. };
  20. class IntegrationServerlessFunctions extends AsyncComponent<Props, State> {
  21. getDefaultState(): State {
  22. return {
  23. ...super.getDefaultState(),
  24. serverlessFunctions: [],
  25. };
  26. }
  27. getEndpoints(): ReturnType<AsyncComponent['getEndpoints']> {
  28. const orgSlug = this.props.organization.slug;
  29. return [
  30. [
  31. 'serverlessFunctions',
  32. `/organizations/${orgSlug}/integrations/${this.props.integration.id}/serverless-functions/`,
  33. ],
  34. ];
  35. }
  36. get serverlessFunctions() {
  37. return this.state.serverlessFunctions;
  38. }
  39. onLoadAllEndpointsSuccess() {
  40. trackIntegrationAnalytics('integrations.serverless_functions_viewed', {
  41. integration: this.props.integration.provider.key,
  42. integration_type: 'first_party',
  43. num_functions: this.serverlessFunctions.length,
  44. organization: this.props.organization,
  45. });
  46. }
  47. handleFunctionUpdate = (
  48. serverlessFunctionUpdate: Partial<ServerlessFunction>,
  49. index: number
  50. ) => {
  51. const serverlessFunctions = [...this.serverlessFunctions];
  52. const serverlessFunction = {
  53. ...serverlessFunctions[index],
  54. ...serverlessFunctionUpdate,
  55. };
  56. serverlessFunctions[index] = serverlessFunction;
  57. this.setState({serverlessFunctions});
  58. };
  59. renderBody() {
  60. return (
  61. <Fragment>
  62. <Alert type="info">
  63. {t(
  64. 'Manage your AWS Lambda functions below. Only Node and Python runtimes are currently supported.'
  65. )}
  66. </Alert>
  67. <Panel>
  68. <StyledPanelHeader disablePadding hasButtons>
  69. <NameHeader>{t('Name')}</NameHeader>
  70. <LayerStatusWrapper>{t('Layer Status')}</LayerStatusWrapper>
  71. <EnableHeader>{t('Enabled')}</EnableHeader>
  72. </StyledPanelHeader>
  73. <StyledPanelBody>
  74. {this.serverlessFunctions.map((serverlessFunction, i) => (
  75. <IntegrationServerlessRow
  76. key={serverlessFunction.name}
  77. serverlessFunction={serverlessFunction}
  78. onUpdateFunction={(update: Partial<ServerlessFunction>) =>
  79. this.handleFunctionUpdate(update, i)
  80. }
  81. {...this.props}
  82. />
  83. ))}
  84. </StyledPanelBody>
  85. </Panel>
  86. </Fragment>
  87. );
  88. }
  89. }
  90. export default withOrganization(IntegrationServerlessFunctions);
  91. const StyledPanelHeader = styled(PanelHeader)`
  92. padding: ${space(2)};
  93. display: grid;
  94. grid-column-gap: ${space(1)};
  95. align-items: center;
  96. grid-template-columns: 2fr 1fr 0.5fr;
  97. grid-template-areas: 'function-name layer-status enable-switch';
  98. `;
  99. const HeaderText = styled('div')`
  100. flex: 1;
  101. `;
  102. const StyledPanelBody = styled(PanelBody)``;
  103. const NameHeader = styled(HeaderText)`
  104. grid-area: function-name;
  105. `;
  106. const LayerStatusWrapper = styled(HeaderText)`
  107. grid-area: layer-status;
  108. `;
  109. const EnableHeader = styled(HeaderText)`
  110. grid-area: enable-switch;
  111. `;