mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +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   ## View signals in event timeline  
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