mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
chore: use new signal meta properties in event timeline (#8421)
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)
This commit is contained in:
parent
24b9e4987b
commit
7c5fab518f
@ -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 }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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<TimelineEvent, 'icon' | 'type'>) => {
|
||||
if (icon) {
|
||||
return <Icon>{icon}</Icon>;
|
||||
}
|
||||
|
||||
if (type === 'signal') {
|
||||
return <SensorsIcon />;
|
||||
}
|
||||
@ -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;
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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',
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user