Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,15 @@ export function BuildDetailsSidebarAppInfo(props: BuildDetailsSidebarAppInfoProp
<IconLink />
</InfoIcon>
<Text>
{props.projectId && props.appInfo.is_installable ? (
{props.projectId ? (
<InstallableLink
onClick={() => {
openInstallModal(props.projectId!, props.artifactId);
}}
>
Installable
Install
</InstallableLink>
) : (
<Tooltip title={labels.installUnavailableTooltip}>
Not Installable
</Tooltip>
)}
) : null}
</Text>
</Flex>
</Feature>
Expand Down
101 changes: 75 additions & 26 deletions static/app/views/preprod/components/installModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import LoadingIndicator from 'sentry/components/loadingIndicator';
import {IconClose} from 'sentry/icons/iconClose';
import {t, tn} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import {MarkedText} from 'sentry/utils/marked/markedText';
import {useApiQuery} from 'sentry/utils/queryClient';
import useOrganization from 'sentry/utils/useOrganization';
import type {InstallDetailsApiResponse} from 'sentry/views/preprod/types/installDetailsTypes';
Expand Down Expand Up @@ -39,33 +40,71 @@ function InstallModal({projectId, artifactId, closeModal}: InstallModalProps) {
}
);

const header = (
<Flex justify="center" align="center" width="100%" position="relative">
<Heading as="h2">{t('Install App')}</Heading>
<Container
position="absolute"
style={{top: '50%', right: 0, transform: 'translateY(-50%)'}}
>
<Button
onClick={closeModal}
priority="transparent"
icon={<IconClose />}
size="sm"
aria-label={t('Close')}
/>
</Container>
</Flex>
);

if (isPending) {
return (
<Flex direction="column" align="center" gap="md" padding="3xl">
<Flex direction="column" align="center" gap="xl">
{header}
<LoadingIndicator />
<Text>{t('Loading install details...')}</Text>
</Flex>
);
}

if (isError) {
if (isError || !installDetails) {
return (
<Flex direction="column" align="center" gap="md" padding="3xl">
<Flex direction="column" align="center" gap="xl">
{header}
<Text>{t('Error: %s', error?.message || 'Failed to fetch install details')}</Text>
<Button onClick={() => refetch()}>{t('Retry')}</Button>
<Button onClick={closeModal}>{t('Close')}</Button>
</Flex>
);
}

if (!installDetails?.install_url) {
const message = installDetails
? t('No install download link available')
: t('No install details available');
if (!installDetails.install_url) {
if (!installDetails.is_code_signature_valid) {
let errors = null;
if (
installDetails.code_signature_errors &&
installDetails.code_signature_errors.length > 0
) {
errors = (
<CodeSignatureInfo>
{installDetails.code_signature_errors.map(e => (
<Text key={e}>{e}</Text>
))}
</CodeSignatureInfo>
);
}
return (
<Flex direction="column" align="center" gap="xl">
{header}
<Text>{'Code signature is invalid'}</Text>
{errors}
</Flex>
);
}
return (
<Flex direction="column" align="center" gap="md" padding="3xl">
<Text>{message}</Text>
<Button onClick={closeModal}>{t('Close')}</Button>
<Flex direction="column" align="center" gap="xl">
{header}
<Text>{t('No install download link available')}</Text>
</Flex>
);
}
Expand All @@ -89,21 +128,7 @@ function InstallModal({projectId, artifactId, closeModal}: InstallModalProps) {
return (
<Fragment>
<Flex direction="column" align="center" gap="xl">
<Flex justify="center" align="center" width="100%" position="relative">
<Heading as="h2">{t('Install App')}</Heading>
<Container
position="absolute"
style={{top: '50%', right: 0, transform: 'translateY(-50%)'}}
>
<Button
onClick={closeModal}
priority="transparent"
icon={<IconClose />}
size="sm"
aria-label={t('Close')}
/>
</Container>
</Flex>
{header}

<Fragment>
<Stack align="center" gap="md">
Expand Down Expand Up @@ -152,6 +177,14 @@ function InstallModal({projectId, artifactId, closeModal}: InstallModalProps) {
{t('The install link will expire in 12 hours')}
</Text>
</Stack>
{installDetails.release_notes && (
<ReleaseNotesSection direction="column" gap="md">
<Heading as="h3">{t('Release Notes')}</Heading>
<ReleaseNotesContent>
<MarkedText text={installDetails.release_notes} />
</ReleaseNotesContent>
</ReleaseNotesSection>
)}
</Fragment>
</Flex>
</Fragment>
Expand All @@ -168,6 +201,9 @@ export const CodeSignatureInfo = styled('div')`
background: ${p => p.theme.backgroundSecondary};
border-radius: ${space(1)};
border: 1px solid ${p => p.theme.border};
max-width: 100%;
word-break: break-word;
overflow-wrap: break-word;
`;

const Divider = styled(Flex)`
Expand Down Expand Up @@ -195,6 +231,19 @@ const Divider = styled(Flex)`
}
`;

const ReleaseNotesSection = styled(Flex)`
width: 100%;
margin-top: ${p => p.theme.space.xl};
`;

const ReleaseNotesContent = styled('div')`
width: 100%;
padding: ${p => p.theme.space.xl};
background: ${p => p.theme.backgroundSecondary};
border-radius: ${p => p.theme.space.md};
border: 1px solid ${p => p.theme.border};
`;

export function openInstallModal(projectId: string, artifactId: string) {
openModal(
({closeModal}) => (
Expand Down
1 change: 1 addition & 0 deletions static/app/views/preprod/types/installDetailsTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export interface InstallDetailsApiResponse {
install_url?: string;
is_code_signature_valid?: boolean;
profile_name?: string;
release_notes?: string;
}
Loading