actions.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import ActionButton from 'sentry/components/actions/button';
  4. import MenuItemActionLink from 'sentry/components/actions/menuItemActionLink';
  5. import {Button} from 'sentry/components/button';
  6. import ButtonBar from 'sentry/components/buttonBar';
  7. import ConfirmDelete from 'sentry/components/confirmDelete';
  8. import DropdownLink from 'sentry/components/dropdownLink';
  9. import {Tooltip} from 'sentry/components/tooltip';
  10. import {IconEllipsis} from 'sentry/icons/iconEllipsis';
  11. import {t} from 'sentry/locale';
  12. import {space} from 'sentry/styles/space';
  13. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  14. type Props = {
  15. hasAccess: boolean;
  16. hasFeature: boolean;
  17. onDelete: () => void;
  18. onEdit: () => void;
  19. repositoryName: string;
  20. disabled?: boolean;
  21. syncNowButton?: React.ReactElement;
  22. };
  23. function Actions({
  24. repositoryName,
  25. disabled,
  26. onEdit,
  27. onDelete,
  28. hasFeature,
  29. hasAccess,
  30. syncNowButton,
  31. }: Props) {
  32. function renderConfirmDelete(element: React.ReactElement) {
  33. return (
  34. <ConfirmDelete
  35. confirmText={t('Delete Repository')}
  36. message={
  37. <Fragment>
  38. <TextBlock>
  39. <strong>
  40. {t('Removing this repository applies instantly to new events.')}
  41. </strong>
  42. </TextBlock>
  43. <TextBlock>
  44. {t(
  45. 'Debug files from this repository will not be used to symbolicate future events. This may create new issues and alert members in your organization.'
  46. )}
  47. </TextBlock>
  48. </Fragment>
  49. }
  50. confirmInput={repositoryName}
  51. priority="danger"
  52. onConfirm={onDelete}
  53. >
  54. {element}
  55. </ConfirmDelete>
  56. );
  57. }
  58. const actionsDisabled = !hasAccess || !hasFeature || disabled;
  59. return (
  60. <StyledButtonBar gap={1}>
  61. {syncNowButton}
  62. <ButtonTooltip
  63. title={
  64. !hasFeature
  65. ? undefined
  66. : !hasAccess
  67. ? t(
  68. 'You do not have permission to edit custom repositories configurations.'
  69. )
  70. : undefined
  71. }
  72. disabled={actionsDisabled}
  73. >
  74. <ActionBtn disabled={actionsDisabled} onClick={onEdit} size="sm">
  75. {t('Configure')}
  76. </ActionBtn>
  77. </ButtonTooltip>
  78. {actionsDisabled ? (
  79. <ButtonTooltip
  80. title={
  81. !hasFeature
  82. ? undefined
  83. : !hasAccess
  84. ? t(
  85. 'You do not have permission to delete custom repositories configurations.'
  86. )
  87. : undefined
  88. }
  89. disabled={actionsDisabled}
  90. >
  91. <ActionBtn size="sm" disabled>
  92. {t('Delete')}
  93. </ActionBtn>
  94. </ButtonTooltip>
  95. ) : (
  96. renderConfirmDelete(<ActionBtn size="sm">{t('Delete')}</ActionBtn>)
  97. )}
  98. <DropDownWrapper>
  99. <DropdownLink
  100. caret={false}
  101. disabled={actionsDisabled}
  102. customTitle={
  103. <StyledActionButton
  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 StyledActionButton = styled(ActionButton)`
  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. `;