integrationServerlessFunctions.tsx 3.9 KB

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