import {Fragment} from 'react'; import type {RouteComponentProps} from 'react-router'; import {browserHistory} from 'react-router'; import styled from '@emotion/styled'; import {Button} from 'sentry/components/button'; import {ExportQueryType} from 'sentry/components/dataExport'; import DateTime from 'sentry/components/dateTime'; import {IconDownload} from 'sentry/icons'; import {t, tct} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import {normalizeUrl} from 'sentry/utils/withDomainRequired'; import Layout from 'sentry/views/auth/layout'; import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView'; export enum DownloadStatus { EARLY = 'EARLY', VALID = 'VALID', EXPIRED = 'EXPIRED', } type RouteParams = { dataExportId: string; orgId: string; }; type Download = { checksum: string; dateCreated: string; id: number; query: { info: object; type: ExportQueryType; }; status: DownloadStatus; user: { email: string; id: number; username: string; }; dateExpired?: string; dateFinished?: string; }; type Props = {} & RouteComponentProps; type State = { download: Download; errors: { download: { responseJSON: { detail: string; }; status: number; statusText: string; }; }; } & DeprecatedAsyncView['state']; class DataDownload extends DeprecatedAsyncView { disableErrorReport = false; getTitle(): string { return t('Download Center'); } getEndpoints(): ReturnType { const {orgId, dataExportId} = this.props.params; return [['download', `/organizations/${orgId}/data-export/${dataExportId}/`]]; } getActionLink(queryType): string { const {orgId} = this.props.params; switch (queryType) { case ExportQueryType.ISSUES_BY_TAG: return `/organizations/${orgId}/issues/`; case ExportQueryType.DISCOVER: return `/organizations/${orgId}/discover/queries/`; default: return '/'; } } renderDate(date: string | undefined): React.ReactNode { if (!date) { return null; } const d = new Date(date); return ( ); } renderEarly(): React.ReactNode { return (

{t('What are')} {t(' you ')} {t('doing here?')}

{t( "Not that its any of our business, but were you invited to this page? It's just that we don't exactly remember emailing you about it." )}

{t("Close this window and we'll email you when your download is ready.")}

); } renderExpired(): React.ReactNode { const {query} = this.state.download; const actionLink = this.getActionLink(query.type); return (

{t('This is awkward.')}

{t( "That link expired, so your download doesn't live here anymore. Just picked up one day and left town." )}

{t( 'Make a new one with your latest data. Your old download will never see it coming.' )}

{t('Start a New Download')}
); } openInDiscover() { const { download: { query: {info}, }, } = this.state; const {orgId} = this.props.params; const to = { pathname: `/organizations/${orgId}/discover/results/`, query: info, }; browserHistory.push(normalizeUrl(to)); } renderOpenInDiscover() { const { download: { query = { type: ExportQueryType.ISSUES_BY_TAG, info: {}, }, }, } = this.state; // default to IssuesByTag because we don't want to // display this unless we're sure its a discover query const {type = ExportQueryType.ISSUES_BY_TAG} = query; return type === 'Discover' ? (

{t('Need to make changes?')}


) : null; } renderValid(): React.ReactNode { const { download: {dateExpired, checksum}, } = this.state; const {orgId, dataExportId} = this.props.params; return (

{t('All done.')}

{t("See, that wasn't so bad. Your data is all ready for download.")}

{t("That link won't last forever — it expires:")}
{this.renderDate(dateExpired)}

{this.renderOpenInDiscover()}

SHA1:{checksum}
{tct('Need help verifying? [link].', { link: ( {t('Check out our docs')} ), })}

); } renderError(): React.ReactNode { const { errors: {download: err}, } = this.state; const errDetail = err?.responseJSON?.detail; return (

{err.status} - {err.statusText}

{errDetail && (

{errDetail}

)}
); } renderContent(): React.ReactNode { const {download} = this.state; switch (download.status) { case DownloadStatus.EARLY: return this.renderEarly(); case DownloadStatus.EXPIRED: return this.renderExpired(); default: return this.renderValid(); } } renderBody() { return (
{this.renderContent()}
); } } const Header = styled('header')` border-bottom: 1px solid ${p => p.theme.border}; padding: ${space(3)} 40px 0; h3 { font-size: 24px; margin: 0 0 ${space(3)} 0; } `; const Body = styled('div')` padding: ${space(2)} 40px; max-width: 500px; p { margin: ${space(1.5)} 0; } `; const DownloadButton = styled(Button)` margin-bottom: ${space(1.5)}; `; export default DataDownload;