diff --git a/frontend/src/component/events/EventTimeline/EventTimeline.tsx b/frontend/src/component/events/EventTimeline/EventTimeline.tsx index 9d4f85ccbcad..c60d145ce54d 100644 --- a/frontend/src/component/events/EventTimeline/EventTimeline.tsx +++ b/frontend/src/component/events/EventTimeline/EventTimeline.tsx @@ -14,12 +14,14 @@ export type TimelineEventType = 'signal' | EventSchemaType; type RawTimelineEvent = EventSchema | ISignalQuerySignal; -type TimelineEvent = { +export type TimelineEvent = { id: number; timestamp: number; type: TimelineEventType; label: string; summary: string; + icon?: string; + variant?: string; }; export type TimelineEventGroup = TimelineEvent[]; @@ -111,6 +113,9 @@ const getTimestamp = (event: RawTimelineEvent) => { const isInRange = (timestamp: number, startTime: number, endTime: number) => timestamp >= startTime && timestamp <= endTime; +const isValidString = (str: unknown): str is string => + typeof str === 'string' && str.trim().length > 0; + const getTimelineEvent = ( event: RawTimelineEvent, timestamp: number, @@ -122,10 +127,19 @@ const getTimelineEvent = ( sourceName = 'unknown source', sourceDescription, tokenName, + payload: { + experimental_unleash_title, + experimental_unleash_description, + experimental_unleash_icon, + experimental_unleash_variant, + }, } = event; - const label = `Signal: ${sourceName}`; - const summary = `Signal originated from **[${sourceName} (${tokenName})](/integrations/signals)** endpoint${sourceDescription ? `: ${sourceDescription}` : ''}`; + const title = experimental_unleash_title || sourceName; + const label = `Signal: ${title}`; + const summary = experimental_unleash_description + ? `Signal: **[${title}](/integrations/signals)** ${experimental_unleash_description}` + : `Signal originated from **[${sourceName} (${tokenName})](/integrations/signals)** endpoint${sourceDescription ? `: ${sourceDescription}` : ''}`; return { id, @@ -133,6 +147,12 @@ const getTimelineEvent = ( type: 'signal', label, summary, + ...(isValidString(experimental_unleash_icon) + ? { icon: experimental_unleash_icon } + : {}), + ...(isValidString(experimental_unleash_variant) + ? { variant: experimental_unleash_variant } + : {}), }; } diff --git a/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventCircle.tsx b/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventCircle.tsx index 0b5e2fd761c5..51be8a841060 100644 --- a/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventCircle.tsx +++ b/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventCircle.tsx @@ -4,14 +4,18 @@ import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined'; import ExtensionOutlinedIcon from '@mui/icons-material/ExtensionOutlined'; import SegmentsIcon from '@mui/icons-material/DonutLargeOutlined'; import QuestionMarkIcon from '@mui/icons-material/QuestionMark'; -import { styled } from '@mui/material'; -import type { TimelineEventGroup, TimelineEventType } from '../EventTimeline'; +import { Icon, styled } from '@mui/material'; +import type { + TimelineEvent, + TimelineEventGroup, + TimelineEventType, +} from '../EventTimeline'; import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; import type { HTMLAttributes } from 'react'; import SensorsIcon from '@mui/icons-material/Sensors'; type DefaultEventVariant = 'secondary'; -type CustomEventVariant = 'success' | 'neutral' | 'warning'; +type CustomEventVariant = 'success' | 'neutral' | 'warning' | 'error'; type EventVariant = DefaultEventVariant | CustomEventVariant; const StyledEventCircle = styled('div', { @@ -26,17 +30,26 @@ const StyledEventCircle = styled('div', { alignItems: 'center', justifyContent: 'center', transition: 'transform 0.2s', - '& svg': { + '& svg, span': { color: theme.palette[variant].main, + }, + '& svg': { height: theme.spacing(2.5), width: theme.spacing(2.5), }, + '& span': { + fontSize: theme.fontSizes.bodySize, + }, '&:hover': { transform: 'scale(1.5)', }, })); -const getEventIcon = (type: TimelineEventType) => { +const getEventIcon = ({ icon, type }: Pick) => { + if (icon) { + return {icon}; + } + if (type === 'signal') { return ; } @@ -72,6 +85,10 @@ const customEventVariants: Partial< 'feature-archived': 'neutral', }; +const isValidVariant = (variant?: string): variant is EventVariant => + variant !== undefined && + ['secondary', 'success', 'neutral', 'warning', 'error'].includes(variant); + interface IEventTimelineEventCircleProps extends HTMLAttributes { group: TimelineEventGroup; @@ -83,16 +100,23 @@ export const EventTimelineEventCircle = ({ }: IEventTimelineEventCircleProps) => { if ( group.length === 1 || - !group.some(({ type }) => type !== group[0].type) + !group.some( + ({ type, icon }) => + type !== group[0].type || icon !== group[0].icon, + ) ) { const event = group[0]; return ( - {getEventIcon(event.type)} + {getEventIcon(event)} ); } diff --git a/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventTooltip/EventTimelineEventTooltip.tsx b/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventTooltip/EventTimelineEventTooltip.tsx index 45c9846bc428..3bf1d36143db 100644 --- a/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventTooltip/EventTimelineEventTooltip.tsx +++ b/frontend/src/component/events/EventTimeline/EventTimelineEventGroup/EventTimelineEventTooltip/EventTimelineEventTooltip.tsx @@ -50,6 +50,7 @@ const StyledTooltipItem = styled('div')(({ theme }) => ({ const StyledEventTimelineEventCircle = styled(EventTimelineEventCircle)( ({ theme }) => ({ + flexShrink: 0, marginTop: theme.spacing(0.125), height: theme.spacing(2.5), width: theme.spacing(2.5), @@ -57,6 +58,9 @@ const StyledEventTimelineEventCircle = styled(EventTimelineEventCircle)( '& > svg': { height: theme.spacing(1.75), }, + '& > span': { + fontSize: theme.fontSizes.smallBody, + }, '&:hover': { transform: 'none', },