repositoryFileSummary.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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('%s file changed in %s', '%s files changed in %s', fileCount, repository)}
  59. </h5>
  60. <ListGroup striped>
  61. {files.map(filename => {
  62. const {authors} = fileChangeSummary[filename];
  63. return (
  64. <FileChange
  65. key={filename}
  66. filename={filename}
  67. authors={authors ? Object.values(authors) : []}
  68. />
  69. );
  70. })}
  71. {numCollapsed > 0 && (
  72. <Collapsed onClick={this.onCollapseToggle} count={numCollapsed} />
  73. )}
  74. {numCollapsed === 0 && canCollapse && (
  75. <ListGroupItem centered>
  76. <a onClick={this.onCollapseToggle}>{t('Collapse')}</a>
  77. </ListGroupItem>
  78. )}
  79. </ListGroup>
  80. </Container>
  81. );
  82. }
  83. }
  84. const Container = styled('div')`
  85. margin-bottom: ${space(2)};
  86. `;
  87. export default RepositoryFileSummary;