|
@@ -8,11 +8,15 @@ import {Button, ButtonProps} from 'sentry/components/button';
|
|
|
import {CompactSelect} from 'sentry/components/compactSelect';
|
|
|
import DateTime from 'sentry/components/dateTime';
|
|
|
import {DropdownMenu} from 'sentry/components/dropdownMenu';
|
|
|
+import FeatureBadge from 'sentry/components/featureBadge';
|
|
|
+import TimeSince from 'sentry/components/timeSince';
|
|
|
import {Tooltip} from 'sentry/components/tooltip';
|
|
|
import {
|
|
|
IconChevron,
|
|
|
IconCopy,
|
|
|
IconEllipsis,
|
|
|
+ IconJson,
|
|
|
+ IconLink,
|
|
|
IconNext,
|
|
|
IconOpen,
|
|
|
IconPrevious,
|
|
@@ -46,6 +50,11 @@ type GroupEventCarouselProps = {
|
|
|
projectSlug: string;
|
|
|
};
|
|
|
|
|
|
+type GroupEventNavigationProps = {
|
|
|
+ group: Group;
|
|
|
+ relativeTime: string;
|
|
|
+};
|
|
|
+
|
|
|
type EventNavigationButtonProps = {
|
|
|
disabled: boolean;
|
|
|
group: Group;
|
|
@@ -59,19 +68,13 @@ enum EventNavDropdownOption {
|
|
|
RECOMMENDED = 'recommended',
|
|
|
LATEST = 'latest',
|
|
|
OLDEST = 'oldest',
|
|
|
+ CUSTOM = 'custom',
|
|
|
ALL = 'all',
|
|
|
}
|
|
|
|
|
|
const BUTTON_SIZE = 'sm';
|
|
|
const BUTTON_ICON_SIZE = 'sm';
|
|
|
|
|
|
-const EVENT_NAV_DROPDOWN_OPTIONS = [
|
|
|
- {value: EventNavDropdownOption.RECOMMENDED, label: 'Recommended Event'},
|
|
|
- {value: EventNavDropdownOption.LATEST, label: 'Latest Event'},
|
|
|
- {value: EventNavDropdownOption.OLDEST, label: 'Oldest Event'},
|
|
|
- {options: [{value: EventNavDropdownOption.ALL, label: 'View All Events'}]},
|
|
|
-];
|
|
|
-
|
|
|
const makeBaseEventsPath = ({
|
|
|
organization,
|
|
|
group,
|
|
@@ -112,7 +115,7 @@ function EventNavigationButton({
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-function EventNavigationDropdown({group}: {group: Group}) {
|
|
|
+function EventNavigationDropdown({group, relativeTime}: GroupEventNavigationProps) {
|
|
|
const location = useLocation();
|
|
|
const params = useParams<{eventId?: string}>();
|
|
|
const theme = useTheme();
|
|
@@ -141,13 +144,54 @@ function EventNavigationDropdown({group}: {group: Group}) {
|
|
|
};
|
|
|
|
|
|
const selectedValue = getSelectedOption();
|
|
|
+ const eventNavDropdownOptions = [
|
|
|
+ {
|
|
|
+ value: EventNavDropdownOption.RECOMMENDED,
|
|
|
+ label: (
|
|
|
+ <div>
|
|
|
+ {t('Recommended')}
|
|
|
+ <FeatureBadge type="new" />
|
|
|
+ </div>
|
|
|
+ ),
|
|
|
+ textValue: t('Recommended'),
|
|
|
+ details: t('Event with the most context'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: EventNavDropdownOption.LATEST,
|
|
|
+ label: t('Latest'),
|
|
|
+ details: t('Last seen event in this issue'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: EventNavDropdownOption.OLDEST,
|
|
|
+ label: t('Oldest'),
|
|
|
+ details: t('First seen event in this issue'),
|
|
|
+ },
|
|
|
+ ...(!selectedValue
|
|
|
+ ? [
|
|
|
+ {
|
|
|
+ value: EventNavDropdownOption.CUSTOM,
|
|
|
+ label: t('Custom Selection'),
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ : []),
|
|
|
+ {
|
|
|
+ options: [{value: EventNavDropdownOption.ALL, label: 'View All Events'}],
|
|
|
+ },
|
|
|
+ ];
|
|
|
|
|
|
return (
|
|
|
<CompactSelect
|
|
|
size="sm"
|
|
|
- options={EVENT_NAV_DROPDOWN_OPTIONS}
|
|
|
- value={selectedValue}
|
|
|
- triggerLabel={!selectedValue ? 'Navigate Events' : undefined}
|
|
|
+ options={eventNavDropdownOptions}
|
|
|
+ value={!selectedValue ? EventNavDropdownOption.CUSTOM : selectedValue}
|
|
|
+ triggerLabel={
|
|
|
+ !selectedValue ? (
|
|
|
+ <TimeSince date={relativeTime} disabledAbsoluteTooltip />
|
|
|
+ ) : selectedValue === EventNavDropdownOption.RECOMMENDED ? (
|
|
|
+ t('Recommended')
|
|
|
+ ) : undefined
|
|
|
+ }
|
|
|
+ menuWidth={232}
|
|
|
onChange={selectedOption => {
|
|
|
switch (selectedOption.value) {
|
|
|
case EventNavDropdownOption.RECOMMENDED:
|
|
@@ -337,20 +381,39 @@ export function GroupEventCarousel({event, group, projectSlug}: GroupEventCarous
|
|
|
]}
|
|
|
/>
|
|
|
{xlargeViewport && (
|
|
|
- <Button size={BUTTON_SIZE} onClick={copyLink}>
|
|
|
- Copy Link
|
|
|
+ <Button
|
|
|
+ title={
|
|
|
+ isHelpfulEventUiEnabled ? t('Copy link to this issue event') : undefined
|
|
|
+ }
|
|
|
+ size={BUTTON_SIZE}
|
|
|
+ onClick={copyLink}
|
|
|
+ aria-label={t('Copy Link')}
|
|
|
+ icon={isHelpfulEventUiEnabled ? <IconLink /> : undefined}
|
|
|
+ >
|
|
|
+ {!isHelpfulEventUiEnabled && 'Copy Link'}
|
|
|
</Button>
|
|
|
)}
|
|
|
{xlargeViewport && (
|
|
|
<Button
|
|
|
+ title={isHelpfulEventUiEnabled ? t('View JSON') : undefined}
|
|
|
size={BUTTON_SIZE}
|
|
|
- icon={<IconOpen size={BUTTON_ICON_SIZE} />}
|
|
|
onClick={downloadJson}
|
|
|
+ aria-label={t('View JSON')}
|
|
|
+ icon={
|
|
|
+ isHelpfulEventUiEnabled ? (
|
|
|
+ <IconJson />
|
|
|
+ ) : (
|
|
|
+ <IconOpen size={BUTTON_ICON_SIZE} />
|
|
|
+ )
|
|
|
+ }
|
|
|
>
|
|
|
- JSON
|
|
|
+ {!isHelpfulEventUiEnabled && 'JSON'}
|
|
|
</Button>
|
|
|
)}
|
|
|
- <EventNavigationDropdown group={group} />
|
|
|
+ <EventNavigationDropdown
|
|
|
+ group={group}
|
|
|
+ relativeTime={event.dateCreated ?? event.dateReceived}
|
|
|
+ />
|
|
|
<NavButtons>
|
|
|
{!isHelpfulEventUiEnabled && (
|
|
|
<EventNavigationButton
|