integrationServerlessFunctions.tsx 4.0 KB

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