Skip to content

Commit

Permalink
chore: use new signal meta properties in event timeline (#8421)
Browse files Browse the repository at this point in the history
https://linear.app/unleash/issue/2-2796/better-signals-integration

Adds support to the following signal payload meta properties:
 - `unleash_title`
 - `unleash_description`
 - `unleash_icon`
 - `unleash_variant`

Follows a logic similar to what we currently have for banners. E.g.
[custom icon](https://docs.getunleash.io/reference/banners#custom-icon).

## Call signal endpoints

![image](https://github.com/user-attachments/assets/7c806a96-5aa4-40a7-b24e-27ab8dc4e374)

![image](https://github.com/user-attachments/assets/6edfd45d-d702-4bd3-9af8-d3655528b09e)


## View signals in event timeline

![image](https://github.com/user-attachments/assets/b3852686-e2c8-407c-b968-b52a1686fdd6)

![image](https://github.com/user-attachments/assets/b47683c5-51b6-426c-96d1-7308fc9e6eab)
  • Loading branch information
nunogois authored Oct 10, 2024
1 parent 24b9e49 commit 7c5fab5
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 11 deletions.
26 changes: 23 additions & 3 deletions frontend/src/component/events/EventTimeline/EventTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand Down Expand Up @@ -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,
Expand All @@ -122,17 +127,32 @@ 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,
timestamp,
type: 'signal',
label,
summary,
...(isValidString(experimental_unleash_icon)
? { icon: experimental_unleash_icon }
: {}),
...(isValidString(experimental_unleash_variant)
? { variant: experimental_unleash_variant }
: {}),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', {
Expand All @@ -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<TimelineEvent, 'icon' | 'type'>) => {
if (icon) {
return <Icon>{icon}</Icon>;
}

if (type === 'signal') {
return <SensorsIcon />;
}
Expand Down Expand Up @@ -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<HTMLDivElement> {
group: TimelineEventGroup;
Expand All @@ -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 (
<StyledEventCircle
variant={customEventVariants[event.type]}
variant={
isValidVariant(event.variant)
? event.variant
: customEventVariants[event.type]
}
{...props}
>
{getEventIcon(event.type)}
{getEventIcon(event)}
</StyledEventCircle>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,17 @@ 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),
transition: 'none',
'& > svg': {
height: theme.spacing(1.75),
},
'& > span': {
fontSize: theme.fontSizes.smallBody,
},
'&:hover': {
transform: 'none',
},
Expand Down

0 comments on commit 7c5fab5

Please sign in to comment.