actions.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import MenuItemActionLink from 'sentry/components/actions/menuItemActionLink';
  4. import {Button} from 'sentry/components/button';
  5. import ButtonBar from 'sentry/components/buttonBar';
  6. import ConfirmDelete from 'sentry/components/confirmDelete';
  7. import DropdownLink from 'sentry/components/dropdownLink';
  8. import {Tooltip} from 'sentry/components/tooltip';
  9. import {IconEllipsis} from 'sentry/icons/iconEllipsis';
  10. import {t} from 'sentry/locale';
  11. import {space} from 'sentry/styles/space';
  12. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  13. type Props = {
  14. hasAccess: boolean;
  15. hasFeature: boolean;
  16. onDelete: () => void;
  17. onEdit: () => void;
  18. repositoryName: string;
  19. disabled?: boolean;
  20. syncNowButton?: React.ReactElement;
  21. };
  22. function Actions({
  23. repositoryName,
  24. disabled,
  25. onEdit,
  26. onDelete,
  27. hasFeature,
  28. hasAccess,
  29. syncNowButton,
  30. }: Props) {
  31. function renderConfirmDelete(element: React.ReactElement) {
  32. return (
  33. <ConfirmDelete
  34. confirmText={t('Delete Repository')}
  35. message={
  36. <Fragment>
  37. <TextBlock>
  38. <strong>
  39. {t('Removing this repository applies instantly to new events.')}
  40. </strong>
  41. </TextBlock>
  42. <TextBlock>
  43. {t(
  44. 'Debug files from this repository will not be used to symbolicate future events. This may create new issues and alert members in your organization.'
  45. )}
  46. </TextBlock>
  47. </Fragment>
  48. }
  49. confirmInput={repositoryName}
  50. priority="danger"
  51. onConfirm={onDelete}
  52. >
  53. {element}
  54. </ConfirmDelete>
  55. );
  56. }
  57. const actionsDisabled = !hasAccess || !hasFeature || disabled;
  58. return (
  59. <StyledButtonBar gap={1}>
  60. {syncNowButton}
  61. <ButtonTooltip
  62. title={
  63. !hasFeature
  64. ? undefined
  65. : !hasAccess
  66. ? t(
  67. 'You do not have permission to edit custom repositories configurations.'
  68. )
  69. : undefined
  70. }
  71. disabled={actionsDisabled}
  72. >
  73. <ActionBtn disabled={actionsDisabled} onClick={onEdit} size="sm">
  74. {t('Configure')}
  75. </ActionBtn>
  76. </ButtonTooltip>
  77. {actionsDisabled ? (
  78. <ButtonTooltip
  79. title={
  80. !hasFeature
  81. ? undefined
  82. : !hasAccess
  83. ? t(
  84. 'You do not have permission to delete custom repositories configurations.'
  85. )
  86. : undefined
  87. }
  88. disabled={actionsDisabled}
  89. >
  90. <ActionBtn size="sm" disabled>
  91. {t('Delete')}
  92. </ActionBtn>
  93. </ButtonTooltip>
  94. ) : (
  95. renderConfirmDelete(<ActionBtn size="sm">{t('Delete')}</ActionBtn>)
  96. )}
  97. <DropDownWrapper>
  98. <DropdownLink
  99. caret={false}
  100. disabled={actionsDisabled}
  101. customTitle={
  102. <StyledButton
  103. size="xs"
  104. aria-label={t('Actions')}
  105. disabled={actionsDisabled}
  106. title={
  107. !hasFeature
  108. ? undefined
  109. : !hasAccess
  110. ? t(
  111. 'You do not have permission to edit and delete custom repositories configurations.'
  112. )
  113. : undefined
  114. }
  115. icon={<IconEllipsis />}
  116. />
  117. }
  118. anchorRight
  119. >
  120. <MenuItemActionLink onClick={onEdit}>{t('Configure')}</MenuItemActionLink>
  121. {renderConfirmDelete(<MenuItemActionLink>{t('Delete')}</MenuItemActionLink>)}
  122. </DropdownLink>
  123. </DropDownWrapper>
  124. </StyledButtonBar>
  125. );
  126. }
  127. export default Actions;
  128. const StyledButton = styled(Button)`
  129. height: 32px;
  130. `;
  131. const StyledButtonBar = styled(ButtonBar)`
  132. gap: ${space(1)};
  133. grid-column: 2/2;
  134. grid-row: 4/4;
  135. grid-auto-flow: row;
  136. margin-top: ${space(0.5)};
  137. @media (min-width: ${p => p.theme.breakpoints.small}) {
  138. grid-column: 3/3;
  139. grid-row: 1/3;
  140. grid-auto-flow: column;
  141. margin-top: 0;
  142. }
  143. `;
  144. const ButtonTooltip = styled(Tooltip)`
  145. @media (min-width: ${p => p.theme.breakpoints.small}) {
  146. display: none;
  147. }
  148. `;
  149. const ActionBtn = styled(Button)`
  150. width: 100%;
  151. @media (min-width: ${p => p.theme.breakpoints.small}) {
  152. display: none;
  153. }
  154. `;
  155. const DropDownWrapper = styled('div')`
  156. display: none;
  157. @media (min-width: ${p => p.theme.breakpoints.small}) {
  158. display: block;
  159. }
  160. `;