import {Fragment} from 'react'; import {RouteComponentProps} from 'react-router'; import styled from '@emotion/styled'; import {Location} from 'history'; import FileChange from 'sentry/components/fileChange'; import * as Layout from 'sentry/components/layouts/thirds'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import Pagination from 'sentry/components/pagination'; import Panel from 'sentry/components/panels/panel'; import PanelBody from 'sentry/components/panels/panelBody'; import PanelHeader from 'sentry/components/panels/panelHeader'; import {t, tn} from 'sentry/locale'; import {CommitFile, Organization, Project, Repository} from 'sentry/types'; import {formatVersion} from 'sentry/utils/formatters'; import routeTitleGen from 'sentry/utils/routeTitle'; import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView'; import {getFilesByRepository, getQuery, getReposToRender} from '../utils'; import EmptyState from './emptyState'; import RepositorySwitcher from './repositorySwitcher'; import withReleaseRepos from './withReleaseRepos'; type Props = RouteComponentProps<{release: string}, {}> & { location: Location; orgSlug: Organization['slug']; projectSlug: Project['slug']; release: string; releaseRepos: Repository[]; activeReleaseRepo?: Repository; } & DeprecatedAsyncView['props']; type State = { fileList: CommitFile[]; } & DeprecatedAsyncView['state']; class FilesChanged extends DeprecatedAsyncView { getTitle() { const {params, orgSlug, projectSlug} = this.props; return routeTitleGen( t('Files Changed - Release %s', formatVersion(params.release)), orgSlug, false, projectSlug ); } getDefaultState(): State { return { ...super.getDefaultState(), fileList: [], }; } componentDidUpdate(prevProps: Props, prevState: State) { if (prevProps.activeReleaseRepo?.name !== this.props.activeReleaseRepo?.name) { this.remountComponent(); return; } super.componentDidUpdate(prevProps, prevState); } getEndpoints(): ReturnType { const {activeReleaseRepo: activeRepository, location, release, orgSlug} = this.props; const query = getQuery({location, activeRepository}); return [ [ 'fileList', `/organizations/${orgSlug}/releases/${encodeURIComponent(release)}/commitfiles/`, {query}, ], ]; } renderLoading() { return this.renderBody(); } renderContent() { const {fileList, fileListPageLinks, loading} = this.state; const {activeReleaseRepo} = this.props; if (loading) { return ; } if (!fileList.length) { return ( {!activeReleaseRepo ? t('There are no changed files associated with this release.') : t( 'There are no changed files associated with this release in the %s repository.', activeReleaseRepo.name )} ); } const filesByRepository = getFilesByRepository(fileList); const reposToRender = getReposToRender(Object.keys(filesByRepository)); return ( {reposToRender.map(repoName => { const repoData = filesByRepository[repoName]; const files = Object.keys(repoData); const fileCount = files.length; return ( {repoName} {tn('%s file changed', '%s files changed', fileCount)} {files.map(filename => { const {authors} = repoData[filename]; return ( ); })} ); })} ); } renderBody() { const {activeReleaseRepo, releaseRepos, router, location} = this.props; return ( {releaseRepos.length > 1 && ( )} {this.renderContent()} ); } renderComponent() { return ( {super.renderComponent()} ); } } export default withReleaseRepos(FilesChanged); const StyledFileChange = styled(FileChange)` border-radius: 0; border-left: none; border-right: none; border-top: none; :last-child { border: none; border-radius: 0; } `;