commits.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import {Fragment} from 'react';
  2. import {RouteComponentProps} from 'react-router';
  3. import {Location} from 'history';
  4. import {CommitRow} from 'sentry/components/commitRow';
  5. import * as Layout from 'sentry/components/layouts/thirds';
  6. import LoadingIndicator from 'sentry/components/loadingIndicator';
  7. import Pagination from 'sentry/components/pagination';
  8. import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels';
  9. import {t} from 'sentry/locale';
  10. import {Commit, Organization, Project, Repository} from 'sentry/types';
  11. import {formatVersion} from 'sentry/utils/formatters';
  12. import routeTitleGen from 'sentry/utils/routeTitle';
  13. import AsyncView from 'sentry/views/asyncView';
  14. import {getCommitsByRepository, getQuery, getReposToRender} from '../utils';
  15. import EmptyState from './emptyState';
  16. import RepositorySwitcher from './repositorySwitcher';
  17. import withReleaseRepos from './withReleaseRepos';
  18. type Props = RouteComponentProps<{release: string}, {}> & {
  19. location: Location;
  20. orgSlug: Organization['slug'];
  21. projectSlug: Project['slug'];
  22. release: string;
  23. releaseRepos: Repository[];
  24. activeReleaseRepo?: Repository;
  25. } & AsyncView['props'];
  26. type State = {
  27. commits: Commit[];
  28. } & AsyncView['state'];
  29. class Commits extends AsyncView<Props, State> {
  30. getTitle() {
  31. const {params, orgSlug, projectSlug} = this.props;
  32. return routeTitleGen(
  33. t('Commits - Release %s', formatVersion(params.release)),
  34. orgSlug,
  35. false,
  36. projectSlug
  37. );
  38. }
  39. getDefaultState(): State {
  40. return {
  41. ...super.getDefaultState(),
  42. commits: [],
  43. };
  44. }
  45. componentDidUpdate(prevProps: Props, prevState: State) {
  46. if (prevProps.activeReleaseRepo?.name !== this.props.activeReleaseRepo?.name) {
  47. this.remountComponent();
  48. return;
  49. }
  50. super.componentDidUpdate(prevProps, prevState);
  51. }
  52. getEndpoints(): ReturnType<AsyncView['getEndpoints']> {
  53. const {
  54. projectSlug,
  55. activeReleaseRepo: activeRepository,
  56. location,
  57. orgSlug,
  58. release,
  59. } = this.props;
  60. const query = getQuery({location, activeRepository});
  61. return [
  62. [
  63. 'commits',
  64. `/projects/${orgSlug}/${projectSlug}/releases/${encodeURIComponent(
  65. release
  66. )}/commits/`,
  67. {query},
  68. ],
  69. ];
  70. }
  71. renderLoading() {
  72. return this.renderBody();
  73. }
  74. renderContent() {
  75. const {commits, commitsPageLinks, loading} = this.state;
  76. const {activeReleaseRepo} = this.props;
  77. if (loading) {
  78. return <LoadingIndicator />;
  79. }
  80. if (!commits.length) {
  81. return (
  82. <EmptyState>
  83. {!activeReleaseRepo
  84. ? t('There are no commits associated with this release.')
  85. : t(
  86. 'There are no commits associated with this release in the %s repository.',
  87. activeReleaseRepo.name
  88. )}
  89. </EmptyState>
  90. );
  91. }
  92. const commitsByRepository = getCommitsByRepository(commits);
  93. const reposToRender = getReposToRender(Object.keys(commitsByRepository));
  94. return (
  95. <Fragment>
  96. {reposToRender.map(repoName => (
  97. <Panel key={repoName}>
  98. <PanelHeader>{repoName}</PanelHeader>
  99. <PanelBody>
  100. {commitsByRepository[repoName]?.map(commit => (
  101. <CommitRow key={commit.id} commit={commit} />
  102. ))}
  103. </PanelBody>
  104. </Panel>
  105. ))}
  106. <Pagination pageLinks={commitsPageLinks} />
  107. </Fragment>
  108. );
  109. }
  110. renderBody() {
  111. const {location, router, activeReleaseRepo, releaseRepos} = this.props;
  112. return (
  113. <Fragment>
  114. {releaseRepos.length > 1 && (
  115. <RepositorySwitcher
  116. repositories={releaseRepos}
  117. activeRepository={activeReleaseRepo}
  118. location={location}
  119. router={router}
  120. />
  121. )}
  122. {this.renderContent()}
  123. </Fragment>
  124. );
  125. }
  126. renderComponent() {
  127. return (
  128. <Layout.Body>
  129. <Layout.Main fullWidth>{super.renderComponent()}</Layout.Main>
  130. </Layout.Body>
  131. );
  132. }
  133. }
  134. export default withReleaseRepos(Commits);