integrationExternalMappings.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import React from 'react';
  2. import styled from '@emotion/styled';
  3. import capitalize from 'lodash/capitalize';
  4. import Access from 'app/components/acl/access';
  5. import Button from 'app/components/button';
  6. import Confirm from 'app/components/confirm';
  7. import {Panel, PanelBody, PanelHeader, PanelItem} from 'app/components/panels';
  8. import Tooltip from 'app/components/tooltip';
  9. import {IconAdd, IconDelete, IconEdit} from 'app/icons';
  10. import {t, tct} from 'app/locale';
  11. import space from 'app/styles/space';
  12. import {ExternalActorMapping, Integration} from 'app/types';
  13. import {getIntegrationIcon} from 'app/utils/integrationUtil';
  14. import EmptyMessage from 'app/views/settings/components/emptyMessage';
  15. type Props = {
  16. integration: Integration;
  17. mappings: {id: string; externalName: string; sentryName: string}[];
  18. type: 'team' | 'user';
  19. onCreateOrEdit: (mapping?: ExternalActorMapping) => void;
  20. onDelete: (mapping: ExternalActorMapping) => void;
  21. };
  22. type State = {};
  23. class IntegrationExternalMappings extends React.Component<Props, State> {
  24. render() {
  25. const {integration, mappings, type, onCreateOrEdit, onDelete} = this.props;
  26. return (
  27. <React.Fragment>
  28. <Panel>
  29. <PanelHeader disablePadding hasButtons>
  30. <HeaderLayout>
  31. <ExternalNameColumn>{tct('External [type]', {type})}</ExternalNameColumn>
  32. <SentryNameColumn>{tct('Sentry [type]', {type})}</SentryNameColumn>
  33. <ButtonColumn>
  34. <AddButton
  35. data-test-id="add-mapping-button"
  36. onClick={() => onCreateOrEdit()}
  37. size="xsmall"
  38. icon={<IconAdd size="xs" isCircled />}
  39. >
  40. {tct('Add [type] Mapping', {type})}
  41. </AddButton>
  42. </ButtonColumn>
  43. </HeaderLayout>
  44. </PanelHeader>
  45. <PanelBody>
  46. {!mappings.length && (
  47. <EmptyMessage icon={getIntegrationIcon(integration.provider.key, 'lg')}>
  48. {tct('Set up External [type] Mappings.', {type: capitalize(type)})}
  49. </EmptyMessage>
  50. )}
  51. {mappings.map(item => (
  52. <Access access={['org:integrations']} key={item.id}>
  53. {({hasAccess}) => (
  54. <ConfigPanelItem>
  55. <Layout>
  56. <ExternalNameColumn>{item.externalName}</ExternalNameColumn>
  57. <SentryNameColumn>{item.sentryName}</SentryNameColumn>
  58. <ButtonColumn>
  59. <Tooltip
  60. title={t(
  61. 'You must be an organization owner, manager or admin to edit or remove an external user mapping.'
  62. )}
  63. disabled={hasAccess}
  64. >
  65. <StyledButton
  66. size="small"
  67. icon={<IconEdit size="sm" />}
  68. label={t('edit')}
  69. disabled={!hasAccess}
  70. onClick={() => onCreateOrEdit(item)}
  71. />
  72. <Confirm
  73. disabled={!hasAccess}
  74. onConfirm={() => onDelete(item)}
  75. message={t(
  76. 'Are you sure you want to remove this external user mapping?'
  77. )}
  78. >
  79. <StyledButton
  80. size="small"
  81. icon={<IconDelete size="sm" />}
  82. label={t('delete')}
  83. disabled={!hasAccess}
  84. />
  85. </Confirm>
  86. </Tooltip>
  87. </ButtonColumn>
  88. </Layout>
  89. </ConfigPanelItem>
  90. )}
  91. </Access>
  92. ))}
  93. </PanelBody>
  94. </Panel>
  95. </React.Fragment>
  96. );
  97. }
  98. }
  99. export default IntegrationExternalMappings;
  100. const AddButton = styled(Button)`
  101. text-transform: capitalize;
  102. `;
  103. const Layout = styled('div')`
  104. display: grid;
  105. grid-column-gap: ${space(1)};
  106. width: 100%;
  107. align-items: center;
  108. grid-template-columns: 2.5fr 2.5fr 1fr;
  109. grid-template-areas: 'external-name sentry-name button';
  110. `;
  111. const HeaderLayout = styled(Layout)`
  112. align-items: center;
  113. margin: 0;
  114. margin-left: ${space(2)};
  115. text-transform: uppercase;
  116. `;
  117. const ConfigPanelItem = styled(PanelItem)``;
  118. const StyledButton = styled(Button)`
  119. margin: ${space(0.5)};
  120. `;
  121. //Columns below
  122. const Column = styled('span')`
  123. overflow: hidden;
  124. overflow-wrap: break-word;
  125. `;
  126. const ExternalNameColumn = styled(Column)`
  127. grid-area: external-name;
  128. `;
  129. const SentryNameColumn = styled(Column)`
  130. grid-area: sentry-name;
  131. `;
  132. const ButtonColumn = styled(Column)`
  133. grid-area: button;
  134. text-align: right;
  135. `;