repositoryFileSummary.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import {Component} from 'react';
  2. import styled from '@emotion/styled';
  3. import FileChange from 'sentry/components/fileChange';
  4. import {ListGroup, ListGroupItem} from 'sentry/components/listGroup';
  5. import {t, tn} from 'sentry/locale';
  6. import space from 'sentry/styles/space';
  7. import {FilesByRepository} from 'sentry/types';
  8. type CollapsedProps = {
  9. count: number;
  10. onClick: React.MouseEventHandler<HTMLAnchorElement>;
  11. };
  12. function Collapsed(props: CollapsedProps) {
  13. return (
  14. <ListGroupItem centered>
  15. <a onClick={props.onClick}>
  16. {tn('Show %s collapsed file', 'Show %s collapsed files', props.count)}
  17. </a>
  18. </ListGroupItem>
  19. );
  20. }
  21. type Props = {
  22. collapsible: boolean;
  23. fileChangeSummary: FilesByRepository[string];
  24. maxWhenCollapsed: number;
  25. repository: string;
  26. };
  27. type State = {
  28. collapsed: boolean;
  29. loading: boolean;
  30. };
  31. class RepositoryFileSummary extends Component<Props, State> {
  32. static defaultProps = {
  33. collapsible: true,
  34. maxWhenCollapsed: 5,
  35. };
  36. state: State = {
  37. loading: true,
  38. collapsed: true,
  39. };
  40. onCollapseToggle = () => {
  41. this.setState({
  42. collapsed: !this.state.collapsed,
  43. });
  44. };
  45. render() {
  46. const {repository, fileChangeSummary, collapsible, maxWhenCollapsed} = this.props;
  47. let files = Object.keys(fileChangeSummary);
  48. const fileCount = files.length;
  49. files.sort();
  50. if (this.state.collapsed && collapsible && fileCount > maxWhenCollapsed) {
  51. files = files.slice(0, maxWhenCollapsed);
  52. }
  53. const numCollapsed = fileCount - files.length;
  54. const canCollapse = collapsible && fileCount > maxWhenCollapsed;
  55. return (
  56. <Container>
  57. <h5>
  58. {tn(
  59. '%s file changed in ' + repository,
  60. '%s files changed in ' + repository,
  61. fileCount
  62. )}
  63. </h5>
  64. <ListGroup striped>
  65. {files.map(filename => {
  66. const {authors} = fileChangeSummary[filename];
  67. return (
  68. <FileChange
  69. key={filename}
  70. filename={filename}
  71. authors={authors ? Object.values(authors) : []}
  72. />
  73. );
  74. })}
  75. {numCollapsed > 0 && (
  76. <Collapsed onClick={this.onCollapseToggle} count={numCollapsed} />
  77. )}
  78. {numCollapsed === 0 && canCollapse && (
  79. <ListGroupItem centered>
  80. <a onClick={this.onCollapseToggle}>{t('Collapse')}</a>
  81. </ListGroupItem>
  82. )}
  83. </ListGroup>
  84. </Container>
  85. );
  86. }
  87. }
  88. const Container = styled('div')`
  89. margin-bottom: ${space(2)};
  90. `;
  91. export default RepositoryFileSummary;