repositoryRow.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import React from 'react';
  2. import styled from '@emotion/styled';
  3. import {cancelDeleteRepository, deleteRepository} from 'app/actionCreators/integrations';
  4. import {Client} from 'app/api';
  5. import Access from 'app/components/acl/access';
  6. import Button from 'app/components/button';
  7. import Confirm from 'app/components/confirm';
  8. import {PanelItem} from 'app/components/panels';
  9. import Tooltip from 'app/components/tooltip';
  10. import {IconDelete} from 'app/icons';
  11. import {t} from 'app/locale';
  12. import space from 'app/styles/space';
  13. import {Repository, RepositoryStatus} from 'app/types';
  14. type DefaultProps = {
  15. showProvider?: boolean;
  16. };
  17. type Props = DefaultProps & {
  18. repository: Repository;
  19. api: Client;
  20. orgId: string;
  21. onRepositoryChange?: (data: {id: string; status: RepositoryStatus}) => void;
  22. };
  23. class RepositoryRow extends React.Component<Props> {
  24. static defaultProps: DefaultProps = {
  25. showProvider: false,
  26. };
  27. getStatusLabel(repo: Repository) {
  28. switch (repo.status) {
  29. case RepositoryStatus.PENDING_DELETION:
  30. return 'Deletion Queued';
  31. case RepositoryStatus.DELETION_IN_PROGRESS:
  32. return 'Deletion in Progress';
  33. case RepositoryStatus.DISABLED:
  34. return 'Disabled';
  35. case RepositoryStatus.HIDDEN:
  36. return 'Disabled';
  37. default:
  38. return null;
  39. }
  40. }
  41. cancelDelete = () => {
  42. const {api, orgId, repository, onRepositoryChange} = this.props;
  43. cancelDeleteRepository(api, orgId, repository.id).then(
  44. data => {
  45. if (onRepositoryChange) {
  46. onRepositoryChange(data);
  47. }
  48. },
  49. () => {}
  50. );
  51. };
  52. deleteRepo = () => {
  53. const {api, orgId, repository, onRepositoryChange} = this.props;
  54. deleteRepository(api, orgId, repository.id).then(
  55. data => {
  56. if (onRepositoryChange) {
  57. onRepositoryChange(data);
  58. }
  59. },
  60. () => {}
  61. );
  62. };
  63. get isActive() {
  64. return this.props.repository.status === RepositoryStatus.ACTIVE;
  65. }
  66. render() {
  67. const {repository, showProvider} = this.props;
  68. const isActive = this.isActive;
  69. return (
  70. <Access access={['org:integrations']}>
  71. {({hasAccess}) => (
  72. <StyledPanelItem status={repository.status}>
  73. <RepositoryTitleAndUrl>
  74. <RepositoryTitle>
  75. <strong>{repository.name}</strong>
  76. {!isActive && <small> &mdash; {this.getStatusLabel(repository)}</small>}
  77. {repository.status === RepositoryStatus.PENDING_DELETION && (
  78. <StyledButton
  79. size="xsmall"
  80. onClick={this.cancelDelete}
  81. disabled={!hasAccess}
  82. data-test-id="repo-cancel"
  83. >
  84. {t('Cancel')}
  85. </StyledButton>
  86. )}
  87. </RepositoryTitle>
  88. <div>
  89. {showProvider && <small>{repository.provider.name}</small>}
  90. {showProvider && repository.url && <span>&nbsp;&mdash;&nbsp;</span>}
  91. {repository.url && (
  92. <small>
  93. <a href={repository.url}>{repository.url.replace('https://', '')}</a>
  94. </small>
  95. )}
  96. </div>
  97. </RepositoryTitleAndUrl>
  98. <Tooltip
  99. title={t(
  100. 'You must be an organization owner, manager or admin to remove a repository.'
  101. )}
  102. disabled={hasAccess}
  103. >
  104. <Confirm
  105. disabled={
  106. !hasAccess ||
  107. (!isActive && repository.status !== RepositoryStatus.DISABLED)
  108. }
  109. onConfirm={this.deleteRepo}
  110. message={t(
  111. 'Are you sure you want to remove this repository? All associated commit data will be removed in addition to the repository.'
  112. )}
  113. >
  114. <Button
  115. size="xsmall"
  116. icon={<IconDelete size="xs" />}
  117. label={t('delete')}
  118. disabled={!hasAccess}
  119. />
  120. </Confirm>
  121. </Tooltip>
  122. </StyledPanelItem>
  123. )}
  124. </Access>
  125. );
  126. }
  127. }
  128. const StyledPanelItem = styled(PanelItem)<{status: RepositoryStatus}>`
  129. /* shorter top padding because of title lineheight */
  130. padding: ${space(1)} ${space(2)} ${space(2)};
  131. justify-content: space-between;
  132. align-items: center;
  133. flex: 1;
  134. ${p =>
  135. p.status === RepositoryStatus.DISABLED &&
  136. `
  137. filter: grayscale(1);
  138. opacity: 0.4;
  139. `};
  140. &:last-child {
  141. border-bottom: none;
  142. }
  143. `;
  144. const StyledButton = styled(Button)`
  145. margin-left: ${space(1)};
  146. `;
  147. const RepositoryTitleAndUrl = styled('div')`
  148. display: flex;
  149. flex-direction: column;
  150. `;
  151. const RepositoryTitle = styled('div')`
  152. margin-bottom: ${space(1)};
  153. /* accommodate cancel button height */
  154. line-height: 26px;
  155. `;
  156. export default RepositoryRow;