mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
chore: add event timeline to new in unleash (#8358)
https://linear.app/unleash/issue/2-2729/add-event-timeline-to-new-in-unleash Adds the new event timeline to the "New in Unleash" section. Unlike Signals & Actions, the Event timeline doesn’t have a dedicated page to link to, as it's a global component within the layout. To address this, we extend the "check it out" action in the New in Unleash component by supporting a callback instead of a link. When the user clicks "check it out" for this new item, the page smoothly scrolls to the top, ~~the timeline opens (if it's not already)~~, and a temporary highlight effect is triggered on the timeline header button. Also includes some scouting / slight UX adjustments. https://github.com/user-attachments/assets/fe49f21b-5986-46b2-8fc6-acb4daef9d08
This commit is contained in:
parent
ec1fe6278a
commit
52b7e235fd
11
frontend/src/assets/img/eventTimeline.svg
Normal file
11
frontend/src/assets/img/eventTimeline.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
@ -1,4 +1,4 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useState, type ReactNode } from 'react';
|
||||
import { EventTimelineContext } from './EventTimelineContext';
|
||||
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||
import type { IEnvironment } from 'interfaces/environments';
|
||||
@ -10,22 +10,28 @@ type TimeSpanOption = {
|
||||
markers: string[];
|
||||
};
|
||||
|
||||
type EventTimelineState = {
|
||||
type EventTimelinePersistentState = {
|
||||
open: boolean;
|
||||
timeSpan: TimeSpanOption;
|
||||
environment?: IEnvironment;
|
||||
signalsSuggestionSeen?: boolean;
|
||||
};
|
||||
|
||||
type EventTimelineTemporaryState = {
|
||||
highlighted: boolean;
|
||||
};
|
||||
|
||||
type EventTimelineStateSetters = {
|
||||
setOpen: (open: boolean) => void;
|
||||
setTimeSpan: (timeSpan: TimeSpanOption) => void;
|
||||
setEnvironment: (environment: IEnvironment) => void;
|
||||
setSignalsSuggestionSeen: (seen: boolean) => void;
|
||||
setHighlighted: (highlighted: boolean) => void;
|
||||
};
|
||||
|
||||
export interface IEventTimelineContext
|
||||
extends EventTimelineState,
|
||||
extends EventTimelinePersistentState,
|
||||
EventTimelineTemporaryState,
|
||||
EventTimelineStateSetters {}
|
||||
|
||||
export const timeSpanOptions: TimeSpanOption[] = [
|
||||
@ -77,7 +83,7 @@ export const timeSpanOptions: TimeSpanOption[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const defaultState: EventTimelineState = {
|
||||
const defaultState: EventTimelinePersistentState = {
|
||||
open: false,
|
||||
timeSpan: timeSpanOptions[0],
|
||||
};
|
||||
@ -89,20 +95,30 @@ interface IEventTimelineProviderProps {
|
||||
export const EventTimelineProvider = ({
|
||||
children,
|
||||
}: IEventTimelineProviderProps) => {
|
||||
const [state, setState] = useLocalStorageState<EventTimelineState>(
|
||||
'event-timeline:v1',
|
||||
defaultState,
|
||||
);
|
||||
const [state, setState] =
|
||||
useLocalStorageState<EventTimelinePersistentState>(
|
||||
'event-timeline:v1',
|
||||
defaultState,
|
||||
);
|
||||
const [highlighted, setHighlighted] = useState(false);
|
||||
|
||||
const setField = <K extends keyof EventTimelineState>(
|
||||
const setField = <K extends keyof EventTimelinePersistentState>(
|
||||
key: K,
|
||||
value: EventTimelineState[K],
|
||||
value: EventTimelinePersistentState[K],
|
||||
) => {
|
||||
setState((prevState) => ({ ...prevState, [key]: value }));
|
||||
};
|
||||
|
||||
const onSetHighlighted = (highlighted: boolean) => {
|
||||
setHighlighted(highlighted);
|
||||
if (highlighted) {
|
||||
setTimeout(() => setHighlighted(false), 3000);
|
||||
}
|
||||
};
|
||||
|
||||
const contextValue: IEventTimelineContext = {
|
||||
...state,
|
||||
highlighted,
|
||||
setOpen: (open: boolean) => setField('open', open),
|
||||
setTimeSpan: (timeSpan: TimeSpanOption) =>
|
||||
setField('timeSpan', timeSpan),
|
||||
@ -110,6 +126,7 @@ export const EventTimelineProvider = ({
|
||||
setField('environment', environment),
|
||||
setSignalsSuggestionSeen: (seen: boolean) =>
|
||||
setField('signalsSuggestionSeen', seen),
|
||||
setHighlighted: onSetHighlighted,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
import { type FC, useEffect } from 'react';
|
||||
import { useLastViewedProject } from 'hooks/useLastViewedProject';
|
||||
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
||||
import { EventTimelineProvider } from 'component/events/EventTimeline/EventTimelineProvider';
|
||||
|
||||
const server = testServerSetup();
|
||||
|
||||
@ -18,8 +19,29 @@ beforeEach(() => {
|
||||
window.localStorage.clear();
|
||||
});
|
||||
|
||||
const TestNavigationSidebar: FC<{
|
||||
project?: string;
|
||||
flags?: LastViewedFlag[];
|
||||
}> = ({ project, flags }) => {
|
||||
const { setLastViewed: setProject } = useLastViewedProject();
|
||||
const { setLastViewed: setFlag } = useLastViewedFlags();
|
||||
|
||||
useEffect(() => {
|
||||
setProject(project);
|
||||
flags?.forEach((flag) => {
|
||||
setFlag(flag);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<EventTimelineProvider>
|
||||
<NavigationSidebar />
|
||||
</EventTimelineProvider>
|
||||
);
|
||||
};
|
||||
|
||||
test('switch full mode and mini mode', () => {
|
||||
render(<NavigationSidebar />);
|
||||
render(<TestNavigationSidebar />);
|
||||
|
||||
expect(screen.queryByText('Projects')).toBeInTheDocument();
|
||||
expect(screen.queryByText('Applications')).toBeInTheDocument();
|
||||
@ -42,7 +64,7 @@ test('switch full mode and mini mode', () => {
|
||||
});
|
||||
|
||||
test('persist navigation mode and expansion selection in storage', async () => {
|
||||
render(<NavigationSidebar />);
|
||||
render(<TestNavigationSidebar />);
|
||||
const { value } = createLocalStorage('navigation-mode:v1', {});
|
||||
expect(value).toBe('full');
|
||||
|
||||
@ -70,7 +92,7 @@ test('persist navigation mode and expansion selection in storage', async () => {
|
||||
test('select active item', async () => {
|
||||
render(
|
||||
<Routes>
|
||||
<Route path={'/search'} element={<NavigationSidebar />} />
|
||||
<Route path={'/search'} element={<TestNavigationSidebar />} />
|
||||
</Routes>,
|
||||
{ route: '/search' },
|
||||
);
|
||||
@ -80,30 +102,13 @@ test('select active item', async () => {
|
||||
expect(links[1]).toHaveClass(classes.selected);
|
||||
});
|
||||
|
||||
const SetupComponent: FC<{ project: string; flags: LastViewedFlag[] }> = ({
|
||||
project,
|
||||
flags,
|
||||
}) => {
|
||||
const { setLastViewed: setProject } = useLastViewedProject();
|
||||
const { setLastViewed: setFlag } = useLastViewedFlags();
|
||||
|
||||
useEffect(() => {
|
||||
setProject(project);
|
||||
flags.forEach((flag) => {
|
||||
setFlag(flag);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return <NavigationSidebar />;
|
||||
};
|
||||
|
||||
test('print recent projects and flags', async () => {
|
||||
testServerRoute(server, `/api/admin/projects/projectA/overview`, {
|
||||
name: 'projectNameA',
|
||||
});
|
||||
|
||||
render(
|
||||
<SetupComponent
|
||||
<TestNavigationSidebar
|
||||
project={'projectA'}
|
||||
flags={[{ featureId: 'featureA', projectId: 'projectB' }]}
|
||||
/>,
|
||||
|
@ -16,6 +16,10 @@ import type { NavigationMode } from 'component/layout/MainLayout/NavigationSideb
|
||||
import { NewInUnleashItem } from './NewInUnleashItem';
|
||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||
import { ReactComponent as SignalsPreview } from 'assets/img/signals.svg';
|
||||
import LinearScaleIcon from '@mui/icons-material/LinearScale';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';
|
||||
import { ReactComponent as EventTimelinePreview } from 'assets/img/eventTimeline.svg';
|
||||
|
||||
const StyledNewInUnleash = styled('div')(({ theme }) => ({
|
||||
margin: theme.spacing(2, 0, 1, 0),
|
||||
@ -67,11 +71,15 @@ const StyledSignalsIcon = styled(Signals)(({ theme }) => ({
|
||||
color: theme.palette.primary.main,
|
||||
}));
|
||||
|
||||
const StyledLinearScaleIcon = styled(LinearScaleIcon)(({ theme }) => ({
|
||||
color: theme.palette.primary.main,
|
||||
}));
|
||||
|
||||
type NewItem = {
|
||||
label: string;
|
||||
summary: string;
|
||||
icon: ReactNode;
|
||||
link: string;
|
||||
onCheckItOut: () => void;
|
||||
docsLink: string;
|
||||
show: boolean;
|
||||
longDescription: ReactNode;
|
||||
@ -89,13 +97,17 @@ export const NewInUnleash = ({
|
||||
onItemClick,
|
||||
onMiniModeClick,
|
||||
}: INewInUnleashProps) => {
|
||||
const navigate = useNavigate();
|
||||
const { trackEvent } = usePlausibleTracker();
|
||||
const [seenItems, setSeenItems] = useLocalStorageState(
|
||||
'new-in-unleash-seen:v1',
|
||||
new Set(),
|
||||
);
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const { isOss, isEnterprise } = useUiConfig();
|
||||
const signalsEnabled = useUiFlag('signals');
|
||||
const eventTimelineEnabled = useUiFlag('eventTimeline');
|
||||
|
||||
const { setHighlighted } = useEventTimelineContext();
|
||||
|
||||
const items: NewItem[] = [
|
||||
{
|
||||
@ -103,7 +115,7 @@ export const NewInUnleash = ({
|
||||
summary: 'Listen to signals via Webhooks',
|
||||
icon: <StyledSignalsIcon />,
|
||||
preview: <SignalsPreview />,
|
||||
link: '/integrations/signals',
|
||||
onCheckItOut: () => navigate('/integrations/signals'),
|
||||
docsLink: 'https://docs.getunleash.io/reference/signals',
|
||||
show: isEnterprise() && signalsEnabled,
|
||||
longDescription: (
|
||||
@ -134,6 +146,35 @@ export const NewInUnleash = ({
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'Event timeline',
|
||||
summary: 'Keep track of recent events across all your projects',
|
||||
icon: <StyledLinearScaleIcon />,
|
||||
preview: <EventTimelinePreview />,
|
||||
onCheckItOut: () => {
|
||||
setHighlighted(true);
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
},
|
||||
docsLink: 'https://docs.getunleash.io/reference/events',
|
||||
show: !isOss() && eventTimelineEnabled,
|
||||
longDescription: (
|
||||
<>
|
||||
<p>
|
||||
Monitor recent events across all your projects in one
|
||||
unified timeline.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can access the event timeline from the top menu to
|
||||
get an overview of changes and quickly identify and
|
||||
debug any issues.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const visibleItems = items.filter(
|
||||
@ -172,7 +213,7 @@ export const NewInUnleash = ({
|
||||
({
|
||||
label,
|
||||
icon,
|
||||
link,
|
||||
onCheckItOut,
|
||||
longDescription,
|
||||
docsLink,
|
||||
preview,
|
||||
@ -197,7 +238,7 @@ export const NewInUnleash = ({
|
||||
}}
|
||||
label={label}
|
||||
icon={icon}
|
||||
link={link}
|
||||
onCheckItOut={onCheckItOut}
|
||||
preview={preview}
|
||||
longDescription={longDescription}
|
||||
docsLink={docsLink}
|
||||
|
@ -36,7 +36,7 @@ interface INewInUnleashItemProps {
|
||||
onDismiss: () => void;
|
||||
label: string;
|
||||
longDescription: ReactNode;
|
||||
link: string;
|
||||
onCheckItOut: () => void;
|
||||
docsLink: string;
|
||||
preview?: ReactNode;
|
||||
summary: string;
|
||||
@ -62,7 +62,7 @@ export const NewInUnleashItem = ({
|
||||
onDismiss,
|
||||
label,
|
||||
longDescription,
|
||||
link,
|
||||
onCheckItOut,
|
||||
docsLink,
|
||||
preview,
|
||||
summary,
|
||||
@ -87,7 +87,7 @@ export const NewInUnleashItem = ({
|
||||
onClose={handleTooltipClose}
|
||||
title={label}
|
||||
longDescription={longDescription}
|
||||
link={link}
|
||||
onCheckItOut={onCheckItOut}
|
||||
docsLink={docsLink}
|
||||
preview={preview}
|
||||
>
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
Typography,
|
||||
ClickAwayListener,
|
||||
} from '@mui/material';
|
||||
import { type Link as RouterLink, useNavigate } from 'react-router-dom';
|
||||
import type { Link as RouterLink } from 'react-router-dom';
|
||||
import OpenInNew from '@mui/icons-material/OpenInNew';
|
||||
import { ReactComponent as UnleashLogo } from 'assets/img/logoWithWhiteText.svg';
|
||||
|
||||
@ -22,6 +22,7 @@ const Header = styled(Box)(({ theme }) => ({
|
||||
|
||||
const Body = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
lineHeight: 1.5,
|
||||
}));
|
||||
|
||||
const StyledLink = styled(Link<typeof RouterLink | 'a'>)(({ theme }) => ({
|
||||
@ -57,17 +58,22 @@ const CenteredPreview = styled(Box)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
const LongDescription = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: theme.spacing(1.5),
|
||||
ul: {
|
||||
margin: 0,
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
}));
|
||||
|
||||
const Title = styled(Typography)(({ theme }) => ({
|
||||
padding: theme.spacing(1, 0, 2, 0),
|
||||
lineHeight: 1.5,
|
||||
}));
|
||||
|
||||
const ReadMore = styled(Box)(({ theme }) => ({
|
||||
padding: theme.spacing(2, 0, 4, 0),
|
||||
padding: theme.spacing(3, 0),
|
||||
}));
|
||||
|
||||
export const NewInUnleashTooltip: FC<{
|
||||
@ -75,7 +81,7 @@ export const NewInUnleashTooltip: FC<{
|
||||
title: string;
|
||||
longDescription: ReactNode;
|
||||
docsLink: string;
|
||||
link: string;
|
||||
onCheckItOut: () => void;
|
||||
open: boolean;
|
||||
preview?: ReactNode;
|
||||
onClose: () => void;
|
||||
@ -83,72 +89,68 @@ export const NewInUnleashTooltip: FC<{
|
||||
children,
|
||||
title,
|
||||
longDescription,
|
||||
link,
|
||||
onCheckItOut,
|
||||
docsLink,
|
||||
preview,
|
||||
open,
|
||||
onClose,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<HtmlTooltip
|
||||
disableFocusListener
|
||||
disableHoverListener
|
||||
disableTouchListener
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
maxHeight={800}
|
||||
maxWidth={350}
|
||||
arrow
|
||||
tabIndex={0}
|
||||
placement='right-end'
|
||||
title={
|
||||
<ClickAwayListener onClickAway={onClose}>
|
||||
<Box>
|
||||
<Header>
|
||||
{preview ? (
|
||||
<BottomPreview>{preview}</BottomPreview>
|
||||
) : (
|
||||
<CenteredPreview>
|
||||
<UnleashLogo />
|
||||
</CenteredPreview>
|
||||
)}
|
||||
</Header>
|
||||
<Body>
|
||||
<Title>{title}</Title>
|
||||
<LongDescription>{longDescription}</LongDescription>
|
||||
<ReadMore>
|
||||
<StyledLink
|
||||
component='a'
|
||||
href={docsLink}
|
||||
underline='hover'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
<StyledOpenInNew /> Read more in our
|
||||
documentation
|
||||
</StyledLink>
|
||||
</ReadMore>
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
type='submit'
|
||||
size='small'
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onClose();
|
||||
navigate(link);
|
||||
}}
|
||||
}) => (
|
||||
<HtmlTooltip
|
||||
disableFocusListener
|
||||
disableHoverListener
|
||||
disableTouchListener
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
maxHeight={800}
|
||||
maxWidth={350}
|
||||
arrow
|
||||
tabIndex={0}
|
||||
placement='right-end'
|
||||
title={
|
||||
<ClickAwayListener onClickAway={onClose}>
|
||||
<Box>
|
||||
<Header>
|
||||
{preview ? (
|
||||
<BottomPreview>{preview}</BottomPreview>
|
||||
) : (
|
||||
<CenteredPreview>
|
||||
<UnleashLogo />
|
||||
</CenteredPreview>
|
||||
)}
|
||||
</Header>
|
||||
<Body>
|
||||
<Title>{title}</Title>
|
||||
<LongDescription>{longDescription}</LongDescription>
|
||||
<ReadMore>
|
||||
<StyledLink
|
||||
component='a'
|
||||
href={docsLink}
|
||||
underline='hover'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
Check it out
|
||||
</Button>
|
||||
</Body>
|
||||
</Box>
|
||||
</ClickAwayListener>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</HtmlTooltip>
|
||||
);
|
||||
};
|
||||
<StyledOpenInNew /> Read more in our
|
||||
documentation
|
||||
</StyledLink>
|
||||
</ReadMore>
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
type='submit'
|
||||
size='small'
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
onClose();
|
||||
onCheckItOut();
|
||||
}}
|
||||
>
|
||||
Check it out
|
||||
</Button>
|
||||
</Body>
|
||||
</Box>
|
||||
</ClickAwayListener>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</HtmlTooltip>
|
||||
);
|
||||
|
@ -33,9 +33,7 @@ import { useAdminRoutes } from 'component/admin/useAdminRoutes';
|
||||
import InviteLinkButton from './InviteLink/InviteLinkButton/InviteLinkButton';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { CommandBar } from 'component/commandBar/CommandBar';
|
||||
import LinearScaleIcon from '@mui/icons-material/LinearScale';
|
||||
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';
|
||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||
import { HeaderEventTimelineButton } from './HeaderEventTimelineButton';
|
||||
|
||||
const HeaderComponent = styled(AppBar)(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
@ -109,10 +107,6 @@ const Header = () => {
|
||||
const [openDrawer, setOpenDrawer] = useState(false);
|
||||
const toggleDrawer = () => setOpenDrawer((prev) => !prev);
|
||||
const celebatoryUnleash = useUiFlag('celebrateUnleash');
|
||||
const eventTimeline = useUiFlag('eventTimeline') && !isOss();
|
||||
const { open: showTimeline, setOpen: setShowTimeline } =
|
||||
useEventTimelineContext();
|
||||
const { trackEvent } = usePlausibleTracker();
|
||||
|
||||
const routes = getRoutes();
|
||||
const adminRoutes = useAdminRoutes();
|
||||
@ -187,35 +181,7 @@ const Header = () => {
|
||||
<StyledNav>
|
||||
<StyledUserContainer>
|
||||
<CommandBar />
|
||||
<ConditionallyRender
|
||||
condition={eventTimeline}
|
||||
show={
|
||||
<Tooltip
|
||||
title={
|
||||
showTimeline
|
||||
? 'Hide timeline'
|
||||
: 'Show timeline'
|
||||
}
|
||||
arrow
|
||||
>
|
||||
<StyledIconButton
|
||||
onClick={() => {
|
||||
trackEvent('event-timeline', {
|
||||
props: {
|
||||
eventType: showTimeline
|
||||
? 'close'
|
||||
: 'open',
|
||||
},
|
||||
});
|
||||
setShowTimeline(!showTimeline);
|
||||
}}
|
||||
size='large'
|
||||
>
|
||||
<LinearScaleIcon />
|
||||
</StyledIconButton>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
<HeaderEventTimelineButton />
|
||||
<InviteLinkButton />
|
||||
<Tooltip
|
||||
title={
|
||||
|
@ -0,0 +1,64 @@
|
||||
import { alpha, IconButton, styled, Tooltip } from '@mui/material';
|
||||
import LinearScaleIcon from '@mui/icons-material/LinearScale';
|
||||
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
|
||||
const StyledHeaderEventTimelineButton = styled(IconButton, {
|
||||
shouldForwardProp: (prop) => prop !== 'highlighted',
|
||||
})<{
|
||||
component?: 'a' | 'button';
|
||||
href?: string;
|
||||
target?: string;
|
||||
highlighted?: boolean;
|
||||
}>(({ theme, highlighted }) => ({
|
||||
animation: highlighted ? 'pulse 1.5s infinite linear' : 'none',
|
||||
zIndex: highlighted ? theme.zIndex.tooltip : 'auto',
|
||||
'@keyframes pulse': {
|
||||
'0%': {
|
||||
boxShadow: `0 0 0 0px ${alpha(theme.palette.primary.main, 0.5)}`,
|
||||
transform: 'scale(1)',
|
||||
},
|
||||
'50%': {
|
||||
boxShadow: `0 0 0 15px ${alpha(theme.palette.primary.main, 0.2)}`,
|
||||
transform: 'scale(1.1)',
|
||||
},
|
||||
'100%': {
|
||||
boxShadow: `0 0 0 30px ${alpha(theme.palette.primary.main, 0)}`,
|
||||
transform: 'scale(1)',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export const HeaderEventTimelineButton = () => {
|
||||
const { trackEvent } = usePlausibleTracker();
|
||||
const { isOss } = useUiConfig();
|
||||
const eventTimeline = useUiFlag('eventTimeline') && !isOss();
|
||||
const {
|
||||
open: showTimeline,
|
||||
setOpen: setShowTimeline,
|
||||
highlighted,
|
||||
} = useEventTimelineContext();
|
||||
|
||||
if (!eventTimeline) return null;
|
||||
|
||||
return (
|
||||
<Tooltip title={showTimeline ? 'Hide timeline' : 'Show timeline'} arrow>
|
||||
<StyledHeaderEventTimelineButton
|
||||
highlighted={highlighted}
|
||||
onClick={() => {
|
||||
trackEvent('event-timeline', {
|
||||
props: {
|
||||
eventType: showTimeline ? 'close' : 'open',
|
||||
},
|
||||
});
|
||||
setShowTimeline(!showTimeline);
|
||||
}}
|
||||
size='large'
|
||||
>
|
||||
<LinearScaleIcon />
|
||||
</StyledHeaderEventTimelineButton>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
@ -36,8 +36,7 @@ import { Notifications } from 'component/common/Notifications/Notifications';
|
||||
import { useAdminRoutes } from 'component/admin/useAdminRoutes';
|
||||
import InviteLinkButton from './InviteLink/InviteLinkButton/InviteLinkButton';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import LinearScaleIcon from '@mui/icons-material/LinearScale';
|
||||
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';
|
||||
import { HeaderEventTimelineButton } from './HeaderEventTimelineButton';
|
||||
|
||||
const HeaderComponent = styled(AppBar)(({ theme }) => ({
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
@ -148,9 +147,6 @@ const OldHeader = () => {
|
||||
const onAdminClose = () => setAdminRef(null);
|
||||
const onConfigureClose = () => setConfigRef(null);
|
||||
const celebatoryUnleash = useUiFlag('celebrateUnleash');
|
||||
const eventTimeline = useUiFlag('eventTimeline') && !isOss();
|
||||
const { open: showTimeline, setOpen: setShowTimeline } =
|
||||
useEventTimelineContext();
|
||||
|
||||
const routes = getRoutes();
|
||||
const adminRoutes = useAdminRoutes();
|
||||
@ -250,28 +246,7 @@ const OldHeader = () => {
|
||||
/>
|
||||
</StyledLinks>
|
||||
<StyledUserContainer>
|
||||
<ConditionallyRender
|
||||
condition={eventTimeline}
|
||||
show={
|
||||
<Tooltip
|
||||
title={
|
||||
showTimeline
|
||||
? 'Hide timeline'
|
||||
: 'Show timeline'
|
||||
}
|
||||
arrow
|
||||
>
|
||||
<StyledIconButton
|
||||
onClick={() =>
|
||||
setShowTimeline(!showTimeline)
|
||||
}
|
||||
size='large'
|
||||
>
|
||||
<LinearScaleIcon />
|
||||
</StyledIconButton>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
<HeaderEventTimelineButton />
|
||||
<InviteLinkButton />
|
||||
<Tooltip
|
||||
title={
|
||||
|
Loading…
Reference in New Issue
Block a user