import { useUiFlag } from 'hooks/useUiFlag'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { useLocalStorageState } from 'hooks/useLocalStorageState'; import { Badge, Icon, ListItem, ListItemButton, ListItemIcon, Tooltip, styled, } from '@mui/material'; import Signals from '@mui/icons-material/Sensors'; import type { NavigationMode } from 'component/layout/MainLayout/NavigationSidebar/NavigationMode'; import { NewInUnleashItem, type NewInUnleashItemDetails, } from './NewInUnleashItem'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { ReactComponent as SignalsPreview } from 'assets/img/signals.svg'; import LifecycleStagesImage from 'assets/img/lifecycle-stages.png'; import MonitorHeartIcon from '@mui/icons-material/MonitorHeartOutlined'; import { useNavigate } from 'react-router-dom'; import { formatAssetPath } from 'utils/formatPath'; const StyledNewInUnleash = styled('div')(({ theme }) => ({ margin: theme.spacing(2, 0, 1, 0), borderRadius: theme.shape.borderRadiusMedium, [theme.breakpoints.down('lg')]: { margin: theme.spacing(2), marginBottom: theme.spacing(1), }, })); const StyledListItem = styled(ListItem)(({ theme }) => ({ margin: theme.spacing(1, 0, 1, 0), })); const StyledNewInUnleashHeader = styled('p')(({ theme }) => ({ display: 'flex', alignItems: 'center', lineHeight: 1, gap: theme.spacing(1), '& > span': { color: theme.palette.neutral.main, }, padding: theme.spacing(1, 2), })); const StyledNewInUnleashList = styled('ul')(({ theme }) => ({ display: 'flex', flexDirection: 'column', padding: theme.spacing(1), listStyle: 'none', margin: 0, gap: theme.spacing(1), })); const StyledMiniItemButton = styled(ListItemButton)(({ theme }) => ({ borderRadius: theme.spacing(0.5), borderLeft: `${theme.spacing(0.5)} solid transparent`, '&.Mui-selected': { borderLeft: `${theme.spacing(0.5)} solid ${theme.palette.primary.main}`, }, })); const StyledMiniItemIcon = styled(ListItemIcon)(({ theme }) => ({ minWidth: theme.spacing(4), margin: theme.spacing(0.25, 0), })); const StyledSignalsIcon = styled(Signals)(({ theme }) => ({ color: theme.palette.primary.main, })); const StyledImg = styled('img')(() => ({ maxWidth: '100%', })); interface INewInUnleashProps { mode?: NavigationMode; onMiniModeClick?: () => void; } export const NewInUnleash = ({ mode = 'full', onMiniModeClick, }: INewInUnleashProps) => { const navigate = useNavigate(); const { trackEvent } = usePlausibleTracker(); const [seenItems, setSeenItems] = useLocalStorageState( 'new-in-unleash-seen:v1', new Set(), ); const { isEnterprise } = useUiConfig(); const signalsEnabled = useUiFlag('signals'); const items: NewInUnleashItemDetails[] = [ { label: 'Lifecycle 2.0', summary: 'Track progress of your feature flags', icon: , preview: ( ), docsLink: 'https://docs.getunleash.io/reference/feature-toggles#feature-flag-lifecycle', show: true, longDescription: (

We have updated the names, icons, and colors for the different stages of a feature flag's lifecycle. The stages convey the same meanings as before but now have clearer names that better indicate where you are in the lifecycle.

), }, { label: 'Signals & Actions', summary: 'Listen to signals via Webhooks', icon: , preview: , onCheckItOut: () => navigate('/integrations/signals'), docsLink: 'https://docs.getunleash.io/reference/signals', show: isEnterprise() && signalsEnabled, longDescription: ( <>

It allows you to respond to events in your real-time monitoring system by automating tasks such as disabling a beta feature in response to an increase in errors or a drop in conversion rates.

  • Signal endpoints are used to send signals to Unleash. This allows you to integrate Unleash with any external tool.
  • Actions, which are configured inside projects, allow you to react to those signals and enable or disable flags based on certain conditions.

), }, ]; const visibleItems = items.filter( (item) => item.show && !seenItems.has(item.label), ); if (!visibleItems.length) return null; if (mode === 'mini' && onMiniModeClick) { return ( new_releases ); } return ( new_releases New in Unleash {visibleItems.map( ({ label, icon, onCheckItOut, longDescription, docsLink, preview, summary, beta = false, }) => ( { trackEvent('new-in-unleash-click', { props: { label, }, }); }} onDismiss={() => { trackEvent('new-in-unleash-dismiss', { props: { label, }, }); setSeenItems(new Set([...seenItems, label])); }} label={label} icon={icon} onCheckItOut={onCheckItOut} preview={preview} longDescription={longDescription} docsLink={docsLink} summary={summary} beta={beta} /> ), )} ); };