import * as React from 'react'; import styled from '@emotion/styled'; import {Client} from 'app/api'; import AvatarList from 'app/components/avatar/avatarList'; import Button from 'app/components/button'; import Clipboard from 'app/components/clipboard'; import Hovercard from 'app/components/hovercard'; import LastCommit from 'app/components/lastCommit'; import LoadingError from 'app/components/loadingError'; import LoadingIndicator from 'app/components/loadingIndicator'; import RepoLabel from 'app/components/repoLabel'; import TimeSince from 'app/components/timeSince'; import Version from 'app/components/version'; import {IconCopy} from 'app/icons'; import {t} from 'app/locale'; import space from 'app/styles/space'; import {Deploy, Organization, Release, Repository} from 'app/types'; import {defined} from 'app/utils'; import withApi from 'app/utils/withApi'; import withRelease from 'app/utils/withRelease'; import withRepositories from 'app/utils/withRepositories'; type Props = { api: Client; projectSlug: string; releaseVersion: string; organization: Organization; release?: Release; releaseLoading?: boolean; releaseError?: Error; deploys?: Array; deploysLoading?: boolean; deploysError?: Error; repositories?: Array; repositoriesLoading?: boolean; repositoriesError?: Error; }; type State = { visible: boolean; }; class VersionHoverCard extends React.Component { state: State = { visible: false, }; toggleHovercard() { this.setState({ visible: true, }); } getRepoLink() { const {organization} = this.props; const orgSlug = organization.slug; return { header: null, body: (
{t('Releases are better with commit data!')}

{t( 'Connect a repository to see commit info, files changed, and authors involved in future releases.' )}

), }; } getBody() { const {releaseVersion, release, deploys} = this.props; if (release === undefined || !defined(deploys)) { return {header: null, body: null}; } const {lastCommit} = release; const recentDeploysByEnvironment = deploys.reduce(function (dbe, deploy) { const {dateFinished, environment} = deploy; if (!dbe.hasOwnProperty(environment)) { dbe[environment] = dateFinished; } return dbe; }, {}); let mostRecentDeploySlice = Object.keys(recentDeploysByEnvironment); if (Object.keys(recentDeploysByEnvironment).length > 3) { mostRecentDeploySlice = Object.keys(recentDeploysByEnvironment).slice(0, 3); } return { header: ( {t('Release')} ), body: (
{t('New Issues')}
{release.newGroups}
{release.commitCount}{' '} {release.commitCount !== 1 ? t('commits ') : t('commit ')} {t('by ')}{' '} {release.authors.length}{' '} {release.authors.length !== 1 ? t('authors') : t('author')}{' '}
{lastCommit && } {deploys.length > 0 && (
{t('Deploys')}
{mostRecentDeploySlice.map((env, idx) => { const dateFinished = recentDeploysByEnvironment[env]; return (
{env} {dateFinished && }
); })}
)}
), }; } render() { const { deploysLoading, deploysError, release, releaseLoading, releaseError, repositories, repositoriesLoading, repositoriesError, } = this.props; let header: React.ReactNode = null; let body: React.ReactNode = null; const loading = !!(deploysLoading || releaseLoading || repositoriesLoading); const error = deploysError ?? releaseError ?? repositoriesError; const hasRepos = repositories && repositories.length > 0; if (loading) { body = ; } else if (error) { body = ; } else { const renderObj: {[key: string]: React.ReactNode} = hasRepos && release ? this.getBody() : this.getRepoLink(); header = renderObj.header; body = renderObj.body; } return ( {this.props.children} ); } } export {VersionHoverCard}; export default withApi(withRelease(withRepositories(VersionHoverCard))); const ConnectRepo = styled('div')` padding: ${space(2)}; text-align: center; `; const VersionRepoLabel = styled(RepoLabel)` width: 86px; `; const StyledTimeSince = styled(TimeSince)` color: ${p => p.theme.gray300}; position: absolute; left: 98px; width: 50%; padding: 3px 0; `; const HeaderWrapper = styled('div')` display: flex; align-items: center; justify-content: space-between; `; const VersionWrapper = styled('div')` display: flex; flex: 1; align-items: center; justify-content: flex-end; `; const StyledVersion = styled(Version)` margin-right: ${space(0.5)}; max-width: 190px; `; const ClipboardIconWrapper = styled('span')` &:hover { cursor: pointer; } `;