Skip to content

Commit

Permalink
feat: move timeline to panel (#9243)
Browse files Browse the repository at this point in the history
Moves the event timeline to the personal dashboard from the header when
the `frontendHeaderRedesign` flag is active.

When the flag is active, it also:
- hides the event timeline and corresponding button in the header
- renders the environment selector next to the time selector instead of
at the other end of the header


![image](https://github.com/user-attachments/assets/cccd8f07-d42a-4180-807f-20937019442d)

---------

Co-authored-by: Nuno Góis <[email protected]>
  • Loading branch information
thomasheartman and nunogois authored Feb 6, 2025
1 parent 54e4fd2 commit 56c9584
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import { timeSpanOptions } from '../EventTimelineProvider';
import CloseIcon from '@mui/icons-material/Close';
import { useEventTimelineContext } from '../EventTimelineContext';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { EventTimelineHeaderTip } from './EventTimelineHeaderTip';
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
import { EventTimelineHeaderTip } from './EventTimelineHeaderTip';
import { useUiFlag } from 'hooks/useUiFlag';

const StyledCol = styled('div')(({ theme }) => ({
display: 'flex',
Expand Down Expand Up @@ -49,6 +50,7 @@ export const EventTimelineHeader = ({
const { timeSpan, environment, setOpen, setTimeSpan, setEnvironment } =
useEventTimelineContext();
const { environments } = useEnvironments();
const frontendHeaderRefactor = useUiFlag('frontendHeaderRedesign');

const activeEnvironments = useMemo(
() => environments.filter(({ enabled }) => enabled),
Expand All @@ -65,6 +67,33 @@ export const EventTimelineHeader = ({
}
}, [activeEnvironments]);

const EnvironmentFilter = () => (
<ConditionallyRender
condition={Boolean(environment) && environments.length > 0}
show={() => (
<StyledFilter
select
size='small'
variant='outlined'
value={environment!.name}
onChange={(e) =>
setEnvironment(
environments.find(
({ name }) => name === e.target.value,
) || environments[0],
)
}
>
{environments.map(({ name }) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</StyledFilter>
)}
/>
);

return (
<>
<StyledCol>
Expand Down Expand Up @@ -92,50 +121,30 @@ export const EventTimelineHeader = ({
</MenuItem>
))}
</StyledFilter>
{frontendHeaderRefactor && <EnvironmentFilter />}
</StyledCol>
<EventTimelineHeaderTip />
<StyledCol>
<ConditionallyRender
condition={Boolean(environment) && environments.length > 0}
show={() => (
<StyledFilter
select
{!frontendHeaderRefactor && (
<StyledCol>
<EventTimelineHeaderTip />
<EnvironmentFilter />
<Tooltip title='Hide event timeline' arrow>
<IconButton
aria-label='close'
size='small'
variant='outlined'
value={environment!.name}
onChange={(e) =>
setEnvironment(
environments.find(
({ name }) => name === e.target.value,
) || environments[0],
)
}
onClick={() => {
trackEvent('event-timeline', {
props: {
eventType: 'close',
},
});
setOpen(false);
}}
>
{environments.map(({ name }) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</StyledFilter>
)}
/>
<Tooltip title='Hide event timeline' arrow>
<IconButton
aria-label='close'
size='small'
onClick={() => {
trackEvent('event-timeline', {
props: {
eventType: 'close',
},
});
setOpen(false);
}}
>
<CloseIcon />
</IconButton>
</Tooltip>
</StyledCol>
<CloseIcon />
</IconButton>
</Tooltip>
</StyledCol>
)}
</>
);
};
5 changes: 4 additions & 1 deletion frontend/src/component/layout/MainLayout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
show={<Header />}
/>

<MainLayoutEventTimeline />
<ConditionallyRender
condition={!frontendHeaderRedesign}
show={<MainLayoutEventTimeline />}
/>

<MainLayoutContent>
<SkipNavTarget />
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/component/menu/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ const Header = () => {
<StyledNav>
<StyledUserContainer>
<CommandBar />
<HeaderEventTimelineButton />
<ConditionallyRender
condition={!frontendHeaderRedesign}
show={<HeaderEventTimelineButton />}
/>
<InviteLinkButton />
<Tooltip
title={
Expand Down
51 changes: 51 additions & 0 deletions frontend/src/component/personalDashboard/PersonalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import { fromPersonalDashboardProjectDetailsOutput } from './RemoteData';
import { useEffect } from 'react';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { InfoSection } from './InfoSection';
import { EventTimeline } from 'component/events/EventTimeline/EventTimeline';
import { AccordionContent } from './SharedComponents';
import { Link } from 'react-router-dom';
import { useUiFlag } from 'hooks/useUiFlag';

const WelcomeSection = styled('div')(({ theme }) => ({
display: 'flex',
Expand Down Expand Up @@ -109,6 +113,7 @@ export const PersonalDashboard = () => {
const { splash } = useAuthSplash();
const { isOss } = useUiConfig();
const name = user?.name || '';
const showTimelinePanel = useUiFlag('frontendHeaderRedesign');

usePageTitle(name ? `Dashboard: ${name}` : 'Dashboard');

Expand All @@ -125,8 +130,11 @@ export const PersonalDashboard = () => {
toggleSectionState,
expandFlags,
expandProjects,
expandTimeline,
} = useDashboardState(projects, personalDashboard?.flags ?? []);

const signalsLink = '/integrations/signals';

const [welcomeDialog, setWelcomeDialog] = useLocalStorageState<
'open' | 'closed'
>(
Expand Down Expand Up @@ -175,6 +183,49 @@ export const PersonalDashboard = () => {
</ViewKeyConceptsButton>
</WelcomeSection>

{showTimelinePanel && (
<SectionAccordion
disableGutters
expanded={expandTimeline ?? false}
onChange={() => toggleSectionState('timeline')}
>
<StyledAccordionSummary
expandIcon={
<ExpandMore titleAccess='Toggle timeline section' />
}
id='timeline-panel-header'
aria-controls='timeline-panel-content'
>
<AccordionSummaryText>
<AccordionSummaryHeader>
Timeline of events
</AccordionSummaryHeader>
<AccordionSummarySubtitle>
Overview of recent activities across all
projects in Unleash. Make debugging easier and{' '}
<Link
to={signalsLink}
onClick={() => {
trackEvent('event-timeline', {
props: {
eventType: 'signals clicked',
},
});
}}
>
include external signals
</Link>{' '}
to get a fuller overview.
</AccordionSummarySubtitle>
</AccordionSummaryText>
</StyledAccordionSummary>
<StyledAccordionDetails>
<AccordionContent>
<EventTimeline />
</AccordionContent>
</StyledAccordionDetails>
</SectionAccordion>
)}
<SectionAccordion
disableGutters
expanded={expandProjects ?? true}
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/component/personalDashboard/SharedComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Box, List, styled } from '@mui/material';
import type { Theme } from '@mui/material/styles/createTheme';
import { Box, List, type Theme, styled } from '@mui/material';

export const ContentGridContainer = styled('div')({
containerType: 'inline-size',
Expand Down Expand Up @@ -57,10 +56,13 @@ export const FlagGrid = styled(ContentGrid)(
}),
);

export const GridItem = styled('div', {
export const AccordionContent = styled('div')(({ theme }) => ({
padding: theme.spacing(2, 4),
}));

export const GridItem = styled(AccordionContent, {
shouldForwardProp: (prop) => !['gridArea'].includes(prop.toString()),
})<{ gridArea: string }>(({ theme, gridArea }) => ({
padding: theme.spacing(2, 4),
maxHeight: '100%',
overflowY: 'auto',
gridArea,
Expand Down
17 changes: 15 additions & 2 deletions frontend/src/component/personalDashboard/useDashboardState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ export const useDashboardState = (
activeFlag: PersonalDashboardSchemaFlagsItem | undefined;
expandProjects: boolean;
expandFlags: boolean;
expandTimeline: boolean;
};

const defaultState: State = {
activeProject: undefined,
activeFlag: undefined,
expandProjects: true,
expandFlags: true,
expandTimeline: false,
};

const [state, setState] = useLocalStorageState<State>(
Expand Down Expand Up @@ -76,8 +78,18 @@ export const useDashboardState = (
});
};

const toggleSectionState = (section: 'flags' | 'projects') => {
const property = section === 'flags' ? 'expandFlags' : 'expandProjects';
const toggleSectionState = (section: 'flags' | 'projects' | 'timeline') => {
const getProperty = () => {
switch (section) {
case 'flags':
return 'expandFlags';
case 'projects':
return 'expandProjects';
case 'timeline':
return 'expandTimeline';
}
};
const property = getProperty();
updateState({
[property]: !(state[property] ?? true),
});
Expand All @@ -90,6 +102,7 @@ export const useDashboardState = (
setActiveProject,
expandFlags: state.expandFlags ?? true,
expandProjects: state.expandProjects ?? true,
expandTimeline: state.expandTimeline ?? false,
toggleSectionState,
};
};

0 comments on commit 56c9584

Please sign in to comment.