123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- import styled from '@emotion/styled';
- import {Location} from 'history';
- import {CopyToClipboardButton} from 'sentry/components/copyToClipboardButton';
- import {Body, Hovercard} from 'sentry/components/hovercard';
- import LoadingIndicator from 'sentry/components/loadingIndicator';
- import Version from 'sentry/components/version';
- import {t} from 'sentry/locale';
- import {space} from 'sentry/styles/space';
- import {Organization, Project} from 'sentry/types';
- import {trackAnalytics} from 'sentry/utils/analytics';
- import EventView, {EventData} from 'sentry/utils/discover/eventView';
- import {getShortEventId} from 'sentry/utils/events';
- import {useLocation} from 'sentry/utils/useLocation';
- import EventContext from './eventContext';
- import IssueContext from './issueContext';
- import ReleaseContext from './releaseContext';
- import {NoContextWrapper} from './styles';
- import {ContextType} from './utils';
- const HOVER_DELAY: number = 400;
- type NoContextProps = {
- isLoading: boolean;
- };
- export function NoContext({isLoading}: NoContextProps) {
- return isLoading ? (
- <NoContextWrapper>
- <LoadingIndicator
- data-test-id="quick-context-loading-indicator"
- hideMessage
- size={32}
- />
- </NoContextWrapper>
- ) : (
- <NoContextWrapper>{t('Failed to load context for column.')}</NoContextWrapper>
- );
- }
- function getHoverBody(
- dataRow: EventData,
- contextType: ContextType,
- organization: Organization,
- location?: Location,
- projects?: Project[],
- eventView?: EventView
- ) {
- switch (contextType) {
- case ContextType.ISSUE:
- return <IssueContext dataRow={dataRow} organization={organization} />;
- case ContextType.RELEASE:
- return <ReleaseContext dataRow={dataRow} organization={organization} />;
- case ContextType.EVENT:
- return (
- <EventContext
- dataRow={dataRow}
- organization={organization}
- location={location}
- projects={projects}
- eventView={eventView}
- />
- );
- default:
- return <NoContextWrapper>{t('There is no context available.')}</NoContextWrapper>;
- }
- }
- // NOTE: Will be adding switch cases as more contexts require headers.
- function getHoverHeader(
- dataRow: EventData,
- contextType: ContextType,
- organization: Organization
- ) {
- switch (contextType) {
- case ContextType.RELEASE:
- return (
- <HoverHeader
- title={t('Release')}
- organization={organization}
- copyLabel={<StyledVersion version={dataRow.release} truncate anchor={false} />}
- copyContent={dataRow.release}
- />
- );
- case ContextType.ISSUE:
- return (
- <HoverHeader
- title={t('Issue')}
- organization={organization}
- copyLabel={dataRow.issue}
- copyContent={dataRow.issue}
- />
- );
- case ContextType.EVENT:
- return (
- dataRow.id && (
- <HoverHeader
- title={t('Event ID')}
- organization={organization}
- copyLabel={getShortEventId(dataRow.id)}
- copyContent={dataRow.id}
- />
- )
- );
- default:
- return null;
- }
- }
- type HoverHeaderProps = {
- organization: Organization;
- title: string;
- copyContent?: string;
- copyLabel?: React.ReactNode;
- hideCopy?: boolean;
- };
- function HoverHeader({
- title,
- hideCopy = false,
- copyLabel,
- copyContent,
- organization,
- }: HoverHeaderProps) {
- return (
- <HoverHeaderWrapper>
- {title}
- <HoverHeaderContent>
- {copyLabel}
- {!hideCopy && copyContent && (
- <CopyToClipboardButton
- borderless
- data-test-id="quick-context-hover-header-copy-button"
- iconSize="xs"
- onCopy={() => {
- trackAnalytics('discover_v2.quick_context_header_copy', {
- organization,
- clipBoardTitle: title,
- });
- }}
- size="zero"
- text={copyContent}
- />
- )}
- </HoverHeaderContent>
- </HoverHeaderWrapper>
- );
- }
- type ContextProps = {
- children: React.ReactNode;
- contextType: ContextType;
- dataRow: EventData;
- organization: Organization;
- eventView?: EventView;
- projects?: Project[];
- };
- export function QuickContextHoverWrapper(props: ContextProps) {
- const location = useLocation();
- const {dataRow, contextType, organization, projects, eventView} = props;
- return (
- <HoverWrapper>
- <StyledHovercard
- showUnderline
- delay={HOVER_DELAY}
- header={getHoverHeader(dataRow, contextType, organization)}
- body={getHoverBody(
- dataRow,
- contextType,
- organization,
- location,
- projects,
- eventView
- )}
- >
- {props.children}
- </StyledHovercard>
- </HoverWrapper>
- );
- }
- const StyledHovercard = styled(Hovercard)`
- ${Body} {
- padding: 0;
- }
- min-width: max-content;
- `;
- const HoverWrapper = styled('div')`
- display: flex;
- align-items: center;
- gap: ${space(0.75)};
- `;
- const HoverHeaderWrapper = styled('div')`
- display: flex;
- align-items: center;
- justify-content: space-between;
- `;
- const HoverHeaderContent = styled('div')`
- display: flex;
- flex: 1;
- align-items: center;
- justify-content: flex-end;
- gap: ${space(0.5)};
- `;
- const StyledVersion = styled(Version)`
- max-width: 190px;
- `;
|