|
@@ -14,15 +14,13 @@ import ExternalLink from 'sentry/components/links/externalLink';
|
|
|
import Link from 'sentry/components/links/link';
|
|
|
import Placeholder from 'sentry/components/placeholder';
|
|
|
import type {PlatformKey} from 'sentry/data/platformCategories';
|
|
|
-import {IconCircle, IconCircleFill, IconClose, IconWarning} from 'sentry/icons';
|
|
|
+import {IconClose, IconWarning} from 'sentry/icons';
|
|
|
import {t} from 'sentry/locale';
|
|
|
import {space} from 'sentry/styles/space';
|
|
|
import {
|
|
|
CodecovStatusCode,
|
|
|
- Coverage,
|
|
|
Event,
|
|
|
Frame,
|
|
|
- LineCoverage,
|
|
|
Organization,
|
|
|
Project,
|
|
|
StacktraceLinkResult,
|
|
@@ -40,7 +38,6 @@ import useApi from 'sentry/utils/useApi';
|
|
|
import useOrganization from 'sentry/utils/useOrganization';
|
|
|
import useProjects from 'sentry/utils/useProjects';
|
|
|
|
|
|
-import {OpenInContainer} from './openInContextLine';
|
|
|
import StacktraceLinkModal from './stacktraceLinkModal';
|
|
|
import useStacktraceLink from './useStacktraceLink';
|
|
|
|
|
@@ -97,7 +94,7 @@ function StacktraceLinkSetup({organization, project, event}: StacktraceLinkSetup
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <CodeMappingButtonContainer columnQuantity={2}>
|
|
|
+ <StacktraceLinkWrapper>
|
|
|
<StyledLink to={`/settings/${organization.slug}/integrations/`}>
|
|
|
<StyledIconWrapper>{getIntegrationIcon('github', 'sm')}</StyledIconWrapper>
|
|
|
{t('Add the GitHub or GitLab integration to jump straight to your source code')}
|
|
@@ -105,7 +102,7 @@ function StacktraceLinkSetup({organization, project, event}: StacktraceLinkSetup
|
|
|
<CloseButton priority="link" onClick={dismissPrompt}>
|
|
|
<IconClose size="xs" aria-label={t('Close')} />
|
|
|
</CloseButton>
|
|
|
- </CodeMappingButtonContainer>
|
|
|
+ </StacktraceLinkWrapper>
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -125,55 +122,14 @@ function shouldshowCodecovFeatures(
|
|
|
|
|
|
interface CodecovLinkProps {
|
|
|
event: Event;
|
|
|
- lineNo: number | null;
|
|
|
organization: Organization;
|
|
|
coverageUrl?: string;
|
|
|
- lineCoverage?: LineCoverage[];
|
|
|
status?: CodecovStatusCode;
|
|
|
}
|
|
|
|
|
|
-function getCoverageIcon(lineCoverage, lineNo) {
|
|
|
- const covIndex = lineCoverage.findIndex(line => line[0] === lineNo);
|
|
|
- if (covIndex === -1) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- switch (lineCoverage[covIndex][1]) {
|
|
|
- case Coverage.COVERED:
|
|
|
- return (
|
|
|
- <CoverageIcon>
|
|
|
- <IconCircleFill size="xs" color="green100" style={{position: 'absolute'}} />
|
|
|
- <IconCircle size="xs" color="green300" />
|
|
|
- {t('Covered')}
|
|
|
- </CoverageIcon>
|
|
|
- );
|
|
|
- case Coverage.PARTIAL:
|
|
|
- return (
|
|
|
- <CoverageIcon>
|
|
|
- <IconCircleFill size="xs" color="yellow100" style={{position: 'absolute'}} />
|
|
|
- <IconCircle size="xs" color="yellow300" />
|
|
|
- {t('Partially Covered')}
|
|
|
- </CoverageIcon>
|
|
|
- );
|
|
|
- case Coverage.NOT_COVERED:
|
|
|
- return (
|
|
|
- <CodecovContainer>
|
|
|
- <CoverageIcon>
|
|
|
- <IconCircleFill size="xs" color="red100" style={{position: 'absolute'}} />
|
|
|
- <IconCircle size="xs" color="red300" />
|
|
|
- </CoverageIcon>
|
|
|
- {t('Not Covered')}
|
|
|
- </CodecovContainer>
|
|
|
- );
|
|
|
- default:
|
|
|
- return null;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
function CodecovLink({
|
|
|
coverageUrl,
|
|
|
status = CodecovStatusCode.COVERAGE_EXISTS,
|
|
|
- lineCoverage,
|
|
|
- lineNo,
|
|
|
organization,
|
|
|
event,
|
|
|
}: CodecovLinkProps) {
|
|
@@ -186,31 +142,25 @@ function CodecovLink({
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- if (status === CodecovStatusCode.COVERAGE_EXISTS) {
|
|
|
- if (!coverageUrl || !lineCoverage || !lineNo) {
|
|
|
- return null;
|
|
|
- }
|
|
|
+ if (status !== CodecovStatusCode.COVERAGE_EXISTS || !coverageUrl) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
|
|
|
- const onOpenCodecovLink = () => {
|
|
|
- trackIntegrationAnalytics(StacktraceLinkEvents.CODECOV_LINK_CLICKED, {
|
|
|
- view: 'stacktrace_issue_details',
|
|
|
- organization,
|
|
|
- group_id: event.groupID ? parseInt(event.groupID, 10) : -1,
|
|
|
- ...getAnalyticsDataForEvent(event),
|
|
|
- });
|
|
|
- };
|
|
|
+ const onOpenCodecovLink = () => {
|
|
|
+ trackIntegrationAnalytics(StacktraceLinkEvents.CODECOV_LINK_CLICKED, {
|
|
|
+ view: 'stacktrace_issue_details',
|
|
|
+ organization,
|
|
|
+ group_id: event.groupID ? parseInt(event.groupID, 10) : -1,
|
|
|
+ ...getAnalyticsDataForEvent(event),
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
- return (
|
|
|
- <CodecovContainer>
|
|
|
- {getCoverageIcon(lineCoverage, lineNo)}
|
|
|
- <OpenInLink href={coverageUrl} openInNewTab onClick={onOpenCodecovLink}>
|
|
|
- <StyledIconWrapper>{getIntegrationIcon('codecov', 'sm')}</StyledIconWrapper>
|
|
|
- {t('Open in Codecov')}
|
|
|
- </OpenInLink>
|
|
|
- </CodecovContainer>
|
|
|
- );
|
|
|
- }
|
|
|
- return null;
|
|
|
+ return (
|
|
|
+ <OpenInLink href={coverageUrl} openInNewTab onClick={onOpenCodecovLink}>
|
|
|
+ <StyledIconWrapper>{getIntegrationIcon('codecov', 'sm')}</StyledIconWrapper>
|
|
|
+ {t('Open in Codecov')}
|
|
|
+ </OpenInLink>
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
interface StacktraceLinkProps {
|
|
@@ -306,16 +256,16 @@ export function StacktraceLink({frame, event, line}: StacktraceLinkProps) {
|
|
|
|
|
|
if (isLoading || !match) {
|
|
|
return (
|
|
|
- <CodeMappingButtonContainer columnQuantity={2}>
|
|
|
- <Placeholder height="24px" width="60px" />
|
|
|
- </CodeMappingButtonContainer>
|
|
|
+ <StacktraceLinkWrapper>
|
|
|
+ <Placeholder height="24px" width="120px" />
|
|
|
+ </StacktraceLinkWrapper>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
// Match found - display link to source
|
|
|
if (match.config && match.sourceUrl) {
|
|
|
return (
|
|
|
- <CodeMappingButtonContainer columnQuantity={2}>
|
|
|
+ <StacktraceLinkWrapper>
|
|
|
<OpenInLink
|
|
|
onClick={onOpenLink}
|
|
|
href={`${match!.sourceUrl}#L${frame.lineNo}`}
|
|
@@ -330,13 +280,11 @@ export function StacktraceLink({frame, event, line}: StacktraceLinkProps) {
|
|
|
<CodecovLink
|
|
|
coverageUrl={`${match.codecov?.coverageUrl}#L${frame.lineNo}`}
|
|
|
status={match.codecov?.status}
|
|
|
- lineCoverage={match.codecov?.lineCoverage}
|
|
|
- lineNo={frame.lineNo}
|
|
|
organization={organization}
|
|
|
event={event}
|
|
|
/>
|
|
|
)}
|
|
|
- </CodeMappingButtonContainer>
|
|
|
+ </StacktraceLinkWrapper>
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -359,7 +307,7 @@ export function StacktraceLink({frame, event, line}: StacktraceLinkProps) {
|
|
|
['github', 'gitlab'].includes(integration.provider?.key)
|
|
|
);
|
|
|
return (
|
|
|
- <CodeMappingButtonContainer columnQuantity={2}>
|
|
|
+ <StacktraceLinkWrapper>
|
|
|
<FixMappingButton
|
|
|
priority="link"
|
|
|
icon={
|
|
@@ -392,7 +340,7 @@ export function StacktraceLink({frame, event, line}: StacktraceLinkProps) {
|
|
|
>
|
|
|
{t('Tell us where your source code is')}
|
|
|
</FixMappingButton>
|
|
|
- </CodeMappingButtonContainer>
|
|
|
+ </StacktraceLinkWrapper>
|
|
|
);
|
|
|
}
|
|
|
|
|
@@ -407,8 +355,15 @@ export function StacktraceLink({frame, event, line}: StacktraceLinkProps) {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-export const CodeMappingButtonContainer = styled(OpenInContainer)`
|
|
|
- justify-content: space-between;
|
|
|
+const StacktraceLinkWrapper = styled('div')`
|
|
|
+ display: flex;
|
|
|
+ gap: ${space(2)};
|
|
|
+ color: ${p => p.theme.subText};
|
|
|
+ background-color: ${p => p.theme.background};
|
|
|
+ font-family: ${p => p.theme.text.family};
|
|
|
+ border-bottom: 1px solid ${p => p.theme.border};
|
|
|
+ padding: ${space(0.25)} ${space(3)};
|
|
|
+ box-shadow: ${p => p.theme.dropShadowLight};
|
|
|
min-height: 28px;
|
|
|
`;
|
|
|
|
|
@@ -447,14 +402,3 @@ const CodecovWarning = styled('div')`
|
|
|
gap: ${space(0.75)};
|
|
|
align-items: center;
|
|
|
`;
|
|
|
-
|
|
|
-const CodecovContainer = styled('span')`
|
|
|
- display: flex;
|
|
|
- gap: ${space(0.75)};
|
|
|
-`;
|
|
|
-
|
|
|
-const CoverageIcon = styled('span')`
|
|
|
- display: flex;
|
|
|
- gap: ${space(0.75)};
|
|
|
- align-items: center;
|
|
|
-`;
|